KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jruby > javasupport > proxy > JavaProxyClass


1 /***** BEGIN LICENSE BLOCK *****
2  * Version: CPL 1.0/GPL 2.0/LGPL 2.1
3  *
4  * The contents of this file are subject to the Common Public
5  * License Version 1.0 (the "License"); you may not use this file
6  * except in compliance with the License. You may obtain a copy of
7  * the License at http://www.eclipse.org/legal/cpl-v10.html
8  *
9  * Software distributed under the License is distributed on an "AS
10  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11  * implied. See the License for the specific language governing
12  * rights and limitations under the License.
13  *
14  * Copyright (C) 2006 Kresten Krab Thorup <krab@gnu.org>
15  *
16  * Alternatively, the contents of this file may be used under the terms of
17  * either of the GNU General Public License Version 2 or later (the "GPL"),
18  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
19  * in which case the provisions of the GPL or the LGPL are applicable instead
20  * of those above. If you wish to allow use of your version of this file only
21  * under the terms of either the GPL or the LGPL, and not to allow others to
22  * use your version of this file under the terms of the CPL, indicate your
23  * decision by deleting the provisions above and replace them with the notice
24  * and other provisions required by the GPL or the LGPL. If you do not delete
25  * the provisions above, a recipient may use your version of this file under
26  * the terms of any one of the CPL, the GPL or the LGPL.
27  ***** END LICENSE BLOCK *****/

28
29 package org.jruby.javasupport.proxy;
30
31 import java.beans.BeanInfo JavaDoc;
32 import java.beans.IntrospectionException JavaDoc;
33 import java.beans.Introspector JavaDoc;
34 import java.beans.PropertyDescriptor JavaDoc;
35 import java.lang.reflect.Array JavaDoc;
36 import java.lang.reflect.Constructor JavaDoc;
37 import java.lang.reflect.InvocationTargetException JavaDoc;
38 import java.lang.reflect.Method JavaDoc;
39 import java.lang.reflect.Modifier JavaDoc;
40 import java.security.AccessController JavaDoc;
41 import java.security.PrivilegedActionException JavaDoc;
42 import java.security.PrivilegedExceptionAction JavaDoc;
43 import java.util.ArrayList JavaDoc;
44 import java.util.Arrays JavaDoc;
45 import java.util.HashMap JavaDoc;
46 import java.util.Iterator JavaDoc;
47 import java.util.List JavaDoc;
48 import java.util.Map JavaDoc;
49
50 import org.jruby.Ruby;
51 import org.jruby.RubyArray;
52 import org.jruby.RubyClass;
53 import org.jruby.RubyFixnum;
54 import org.jruby.RubyModule;
55 import org.jruby.RubyObject;
56 import org.jruby.exceptions.RaiseException;
57 import org.jruby.javasupport.Java;
58 import org.jruby.javasupport.JavaClass;
59 import org.jruby.javasupport.JavaObject;
60 import org.jruby.javasupport.JavaUtil;
61 import org.jruby.runtime.Arity;
62 import org.jruby.runtime.Block;
63 import org.jruby.runtime.CallbackFactory;
64 import org.jruby.runtime.ObjectAllocator;
65 import org.jruby.runtime.builtin.IRubyObject;
66 import org.jruby.runtime.callback.Callback;
67
68 /**
69  * Generalized proxy for classes and interfaces.
70  *
71  * API looks a lot like java.lang.reflect.Proxy, except that you can specify a
72  * super class in addition to a set of interfaces.
73  *
74  * The main implication for users of this class is to handle the case where a
75  * proxy method overrides an existing method, because in this case the
76  * invocation handler should "default" to calling the super implementation
77  * {JavaProxyMethod.invokeSuper}.
78  *
79  *
80  * @author krab@trifork.com
81  * @see java.lang.reflect.Proxy
82  *
83  */

84 public class JavaProxyClass extends JavaProxyReflectionObject {
85
86     static ThreadLocal JavaDoc runtimeTLS = new ThreadLocal JavaDoc();
87
88     private final Class JavaDoc proxyClass;
89
90     private ArrayList JavaDoc methods = new ArrayList JavaDoc();
91
92     /* package scope */
93     JavaProxyClass(Class JavaDoc proxyClass) {
94         super(getThreadLocalRuntime(), (RubyClass) getThreadLocalRuntime()
95                 .getModule("Java").getClass("JavaProxyClass"));
96         this.proxyClass = proxyClass;
97     }
98
99     public Object JavaDoc getValue() {
100         return this;
101     }
102
103     private static Ruby getThreadLocalRuntime() {
104         return (Ruby) runtimeTLS.get();
105     }
106
107     public static JavaProxyClass getProxyClass(Ruby runtime, Class JavaDoc superClass,
108             Class JavaDoc[] interfaces) throws InvocationTargetException JavaDoc {
109         Object JavaDoc save = runtimeTLS.get();
110         runtimeTLS.set(runtime);
111         try {
112             ClassLoader JavaDoc loader = runtime.getJavaSupport().getJavaClassLoader();
113
114             return JavaProxyClassFactory.newProxyClass(loader, null,
115                     superClass, interfaces);
116
117         } finally {
118             runtimeTLS.set(save);
119         }
120     }
121
122     public static Object JavaDoc newProxyInstance(Ruby runtime, Class JavaDoc superClass,
123             Class JavaDoc[] interfaces, Class JavaDoc[] constructorParameters,
124             Object JavaDoc[] constructorArgs, JavaProxyInvocationHandler handler)
125             throws IllegalArgumentException JavaDoc, InstantiationException JavaDoc,
126             IllegalAccessException JavaDoc, InvocationTargetException JavaDoc,
127             SecurityException JavaDoc, NoSuchMethodException JavaDoc {
128         JavaProxyClass jpc = getProxyClass(runtime, superClass, interfaces);
129         JavaProxyConstructor cons = jpc
130                 .getConstructor(constructorParameters == null ? new Class JavaDoc[0]
131                         : constructorParameters);
132         return cons.newInstance(constructorArgs, handler);
133
134     }
135
136     public Class JavaDoc getSuperclass() {
137         return proxyClass.getSuperclass();
138     }
139
140     public Class JavaDoc[] getInterfaces() {
141         Class JavaDoc[] ifaces = proxyClass.getInterfaces();
142         Class JavaDoc[] result = new Class JavaDoc[ifaces.length - 1];
143         int pos = 0;
144         for (int i = 0; i < ifaces.length; i++) {
145             if (ifaces[i] != InternalJavaProxy.class) {
146                 result[pos++] = ifaces[i];
147             }
148         }
149         return result;
150     }
151
152     public JavaProxyConstructor[] getConstructors() {
153         Constructor JavaDoc[] cons = proxyClass.getConstructors();
154         JavaProxyConstructor[] result = new JavaProxyConstructor[cons.length];
155         for (int i = 0; i < cons.length; i++) {
156             result[i] = new JavaProxyConstructor(getRuntime(), this, cons[i]);
157         }
158         return result;
159     }
160
161     public JavaProxyConstructor getConstructor(Class JavaDoc[] args)
162             throws SecurityException JavaDoc, NoSuchMethodException JavaDoc {
163
164         Class JavaDoc[] realArgs = new Class JavaDoc[args.length + 1];
165         System.arraycopy(args, 0, realArgs, 0, args.length);
166         realArgs[args.length] = JavaProxyInvocationHandler.class;
167
168         Constructor JavaDoc constructor = proxyClass.getConstructor(realArgs);
169         return new JavaProxyConstructor(getRuntime(), this, constructor);
170     }
171
172     public JavaProxyMethod[] getMethods() {
173         return (JavaProxyMethod[]) methods.toArray(new JavaProxyMethod[methods
174                 .size()]);
175     }
176
177     public JavaProxyMethod getMethod(String JavaDoc name, Class JavaDoc[] parameterTypes)
178             throws NoSuchMethodException JavaDoc {
179         JavaProxyMethod[] all = getMethods();
180         for (int i = 0; i < all.length; i++) {
181             ProxyMethodImpl jpm = (ProxyMethodImpl) all[i];
182             if (jpm.matches(name, parameterTypes)) {
183                 return jpm;
184             }
185         }
186         throw new NoSuchMethodException JavaDoc();
187     }
188
189     /** return the class of instances of this proxy class */
190     Class JavaDoc getProxyClass() {
191         return proxyClass;
192     }
193
194     public static class ProxyMethodImpl extends JavaProxyReflectionObject
195             implements JavaProxyMethod {
196         private final Method JavaDoc m;
197
198         private Object JavaDoc state;
199
200         private final Method JavaDoc sm;
201
202         private final JavaProxyClass clazz;
203
204         public ProxyMethodImpl(Ruby runtime, JavaProxyClass clazz, Method JavaDoc m,
205                 Method JavaDoc sm) {
206             super(runtime, runtime.getModule("Java")
207                     .getClass("JavaProxyMethod"));
208             this.m = m;
209             this.sm = sm;
210             this.clazz = clazz;
211         }
212
213         public Method JavaDoc getMethod() {
214             return m;
215         }
216
217         public Method JavaDoc getSuperMethod() {
218             return sm;
219         }
220
221         public int getModifiers() {
222             return m.getModifiers();
223         }
224
225         public String JavaDoc getName() {
226             return m.getName();
227         }
228
229         public Class JavaDoc[] getExceptionTypes() {
230             return m.getExceptionTypes();
231         }
232
233         public Class JavaDoc[] getParameterTypes() {
234             return m.getParameterTypes();
235         }
236
237         public Object JavaDoc getState() {
238             return state;
239         }
240
241         public boolean hasSuperImplementation() {
242             return sm != null;
243         }
244
245         public Object JavaDoc invoke(Object JavaDoc proxy, Object JavaDoc[] args)
246                 throws IllegalArgumentException JavaDoc, IllegalAccessException JavaDoc,
247                 InvocationTargetException JavaDoc, NoSuchMethodException JavaDoc {
248             if (!hasSuperImplementation()) {
249                 throw new NoSuchMethodException JavaDoc();
250             }
251             return sm.invoke(proxy, args);
252         }
253
254         public void setState(Object JavaDoc state) {
255             this.state = state;
256         }
257
258         public String JavaDoc toString() {
259             return m.toString();
260         }
261
262         public Object JavaDoc defaultResult() {
263             Class JavaDoc rt = m.getReturnType();
264             if (rt == Void.TYPE) {
265                 return null;
266             }
267             if (rt == Boolean.TYPE) {
268                 return Boolean.FALSE;
269             }
270             if (rt == Byte.TYPE) {
271                 return new Byte JavaDoc((byte) 0);
272             }
273             if (rt == Short.TYPE) {
274                 return new Short JavaDoc((short) 0);
275             }
276             if (rt == Integer.TYPE) {
277                 return new Integer JavaDoc(0);
278             }
279             if (rt == Long.TYPE) {
280                 return new Long JavaDoc(0L);
281             }
282             if (rt == Float.TYPE) {
283                 return new Float JavaDoc(0.0f);
284             }
285             if (rt == Double.TYPE) {
286                 return new Double JavaDoc(0.0);
287             }
288             return null;
289         }
290
291         public boolean matches(String JavaDoc name, Class JavaDoc[] parameterTypes) {
292             return m.getName().equals(name)
293                     && Arrays.equals(m.getParameterTypes(), parameterTypes);
294         }
295
296         public Class JavaDoc getReturnType() {
297             return m.getReturnType();
298         }
299         
300         public static RubyClass createJavaProxyMethodClass(Ruby runtime,
301                 RubyModule javaProxyModule) {
302
303             RubyClass result = javaProxyModule.defineClassUnder("JavaProxyMethod", runtime.getObject(), ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);
304
305             CallbackFactory callbackFactory = runtime
306                     .callbackFactory(JavaProxyClass.ProxyMethodImpl.class);
307
308             JavaProxyReflectionObject.registerRubyMethods(runtime, result);
309
310             result.defineFastMethod("argument_types", callbackFactory
311                     .getFastMethod("argument_types"));
312
313             result.defineFastMethod("declaring_class", callbackFactory
314                     .getFastMethod("getDeclaringClass"));
315
316             result.defineFastMethod("super?", callbackFactory.getFastMethod("super_p"));
317
318             result.defineFastMethod("arity", callbackFactory.getFastMethod("arity"));
319
320             result.defineFastMethod("name", callbackFactory.getFastMethod("name"));
321
322             result
323                     .defineFastMethod("inspect", callbackFactory
324                             .getFastMethod("inspect"));
325
326             result.defineFastMethod("invoke", callbackFactory
327                     .getFastOptMethod("do_invoke"));
328
329             return result;
330
331         }
332
333         public RubyObject name() {
334             return getRuntime().newString(getName());
335         }
336
337         public JavaProxyClass getDeclaringClass() {
338             return clazz;
339         }
340
341         public RubyArray argument_types() {
342             return buildRubyArray(getParameterTypes());
343         }
344
345         public IRubyObject super_p() {
346             return hasSuperImplementation() ? getRuntime().getTrue()
347                     : getRuntime().getFalse();
348         }
349
350         public RubyFixnum arity() {
351             return getRuntime().newFixnum(getArity());
352         }
353
354         protected String JavaDoc nameOnInspection() {
355             return getDeclaringClass().nameOnInspection() + "/" + getName();
356         }
357
358         public IRubyObject inspect() {
359             StringBuffer JavaDoc result = new StringBuffer JavaDoc();
360             result.append(nameOnInspection());
361             result.append("(");
362             Class JavaDoc[] parameterTypes = getParameterTypes();
363             for (int i = 0; i < parameterTypes.length; i++) {
364                 result.append(parameterTypes[i].getName());
365                 if (i < parameterTypes.length - 1) {
366                     result.append(',');
367                 }
368             }
369             result.append(")>");
370             return getRuntime().newString(result.toString());
371         }
372
373         public IRubyObject do_invoke(IRubyObject[] nargs) {
374             if (nargs.length != 1 + getArity()) {
375                 throw getRuntime().newArgumentError(nargs.length,
376                         1 + getArity());
377             }
378
379             IRubyObject invokee = nargs[0];
380             if (!(invokee instanceof JavaObject)) {
381                 throw getRuntime().newTypeError("invokee not a java object");
382             }
383             Object JavaDoc receiver_value = ((JavaObject) invokee).getValue();
384             Object JavaDoc[] arguments = new Object JavaDoc[nargs.length - 1];
385             System.arraycopy(nargs, 1, arguments, 0, arguments.length);
386
387             Class JavaDoc[] parameterTypes = getParameterTypes();
388             for (int i = 0; i < arguments.length; i++) {
389                 arguments[i] = JavaUtil.convertRubyToJava(
390                         (IRubyObject) arguments[i], parameterTypes[i]);
391             }
392
393             try {
394                 Object JavaDoc javaResult = sm.invoke(receiver_value, arguments);
395                 return JavaUtil.convertJavaToRuby(getRuntime(), javaResult,
396                         getReturnType());
397             } catch (IllegalArgumentException JavaDoc e) {
398                 throw getRuntime().newTypeError(
399                         "expected " + argument_types().inspect());
400             } catch (IllegalAccessException JavaDoc iae) {
401                 throw getRuntime().newTypeError(
402                         "illegal access on '" + sm.getName() + "': "
403                                 + iae.getMessage());
404             } catch (InvocationTargetException JavaDoc ite) {
405                 ite.getTargetException().printStackTrace();
406                 getRuntime().getJavaSupport().handleNativeException(
407                         ite.getTargetException());
408                 // This point is only reached if there was an exception handler
409
// installed.
410
return getRuntime().getNil();
411             }
412         }
413
414         private int getArity() {
415             return getParameterTypes().length;
416         }
417
418     }
419
420     JavaProxyMethod initMethod(String JavaDoc name, String JavaDoc desc, boolean hasSuper) {
421         Class JavaDoc proxy = proxyClass;
422         try {
423             Class JavaDoc[] parms = parse(proxy.getClassLoader(), desc);
424             Method JavaDoc m = proxy.getDeclaredMethod(name, parms);
425             Method JavaDoc sm = null;
426             if (hasSuper) {
427                 sm = proxy.getDeclaredMethod("__super$" + name, parms);
428             }
429
430             JavaProxyMethod jpm = new ProxyMethodImpl(getRuntime(), this, m, sm);
431             methods.add(jpm);
432             return jpm;
433
434         } catch (ClassNotFoundException JavaDoc e) {
435             throw new InternalError JavaDoc(e.getMessage());
436         } catch (SecurityException JavaDoc e) {
437             throw new InternalError JavaDoc(e.getMessage());
438         } catch (NoSuchMethodException JavaDoc e) {
439             throw new InternalError JavaDoc(e.getMessage());
440         }
441
442     }
443
444     private static Class JavaDoc[] parse(final ClassLoader JavaDoc loader, String JavaDoc desc)
445             throws ClassNotFoundException JavaDoc {
446         List JavaDoc al = new ArrayList JavaDoc();
447         int idx = 1;
448         while (desc.charAt(idx) != ')') {
449
450             int arr = 0;
451             while (desc.charAt(idx) == '[') {
452                 idx += 1;
453                 arr += 1;
454             }
455
456             Class JavaDoc type;
457
458             switch (desc.charAt(idx)) {
459             case 'L':
460                 int semi = desc.indexOf(';', idx);
461                 final String JavaDoc name = desc.substring(idx + 1, semi);
462                 idx = semi;
463                 try {
464                     type = (Class JavaDoc) AccessController
465                             .doPrivileged(new PrivilegedExceptionAction JavaDoc() {
466                                 public Object JavaDoc run()
467                                         throws ClassNotFoundException JavaDoc {
468                                     return Class.forName(
469                                             name.replace('/', '.'), false,
470                                             loader);
471                                 }
472                             });
473                 } catch (PrivilegedActionException JavaDoc e) {
474                     throw (ClassNotFoundException JavaDoc) e.getException();
475                 }
476                 break;
477
478             case 'B':
479                 type = Byte.TYPE;
480                 break;
481
482             case 'C':
483                 type = Character.TYPE;
484                 break;
485
486             case 'Z':
487                 type = Boolean.TYPE;
488                 break;
489
490             case 'S':
491                 type = Short.TYPE;
492                 break;
493
494             case 'I':
495                 type = Integer.TYPE;
496                 break;
497
498             case 'J':
499                 type = Long.TYPE;
500                 break;
501
502             case 'F':
503                 type = Float.TYPE;
504                 break;
505
506             case 'D':
507                 type = Double.TYPE;
508                 break;
509
510             default:
511                 throw new InternalError JavaDoc("cannot parse " + desc + "[" + idx
512                         + "]");
513             }
514
515             idx += 1;
516
517             if (arr != 0) {
518                 type = Array.newInstance(type, new int[arr]).getClass();
519             }
520
521             al.add(type);
522         }
523
524         return (Class JavaDoc[]) al.toArray(new Class JavaDoc[al.size()]);
525     }
526
527     //
528
// Ruby-level methods
529
//
530

531     public static RubyClass createJavaProxyClassClass(Ruby runtime,
532             RubyModule javaModule) {
533         RubyClass result = javaModule.defineClassUnder("JavaProxyClass",
534                                                        runtime.getObject(),ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);
535
536         CallbackFactory callbackFactory = runtime
537                 .callbackFactory(JavaProxyClass.class);
538
539         JavaProxyReflectionObject.registerRubyMethods(runtime, result);
540
541         result.defineFastMethod("constructors", callbackFactory
542                 .getFastMethod("constructors"));
543
544         result.defineFastMethod("superclass", callbackFactory
545                 .getFastMethod("superclass"));
546
547         result.defineFastMethod("interfaces", callbackFactory
548                 .getFastMethod("interfaces"));
549
550         result.defineFastMethod("methods", callbackFactory.getFastMethod("methods"));
551
552         result.getMetaClass().defineFastMethod("get", callbackFactory.getFastSingletonMethod(
553                 "get", JavaClass.class));
554
555         result.defineFastMethod("define_instance_methods_for_proxy",
556                 callbackFactory.getFastMethod("define_instance_methods_for_proxy",
557                         IRubyObject.class));
558
559         return result;
560
561     }
562
563     public static RubyObject get(IRubyObject recv, JavaClass type) {
564         try {
565             return getProxyClass(recv.getRuntime(), (Class JavaDoc) type.getValue(),
566                     new Class JavaDoc[0]);
567         } catch (Error JavaDoc e) {
568             RaiseException ex = recv.getRuntime().newArgumentError(
569                     "unable to create proxy class for " + type.getValue());
570             ex.initCause(e);
571             throw ex;
572         } catch (InvocationTargetException JavaDoc e) {
573             RaiseException ex = recv.getRuntime().newArgumentError(
574                     "unable to create proxy class for " + type.getValue());
575             ex.initCause(e);
576             throw ex;
577         }
578     }
579
580     public RubyObject superclass() {
581         return JavaClass.get(getRuntime(), getSuperclass());
582     }
583
584     public RubyArray methods() {
585         return buildRubyArray(getMethods());
586     }
587
588     public RubyArray interfaces() {
589         Class JavaDoc[] interfaces = getInterfaces();
590         return buildRubyArray(interfaces);
591     }
592
593     public RubyArray constructors() {
594         return buildRubyArray(getConstructors());
595     }
596
597     public static void createJavaProxyModule(Ruby runtime) {
598         // TODO Auto-generated method stub
599

600         RubyModule javaProxyModule = runtime.getModule("Java");
601         JavaProxyClass.createJavaProxyClassClass(runtime, javaProxyModule);
602         ProxyMethodImpl.createJavaProxyMethodClass(runtime, javaProxyModule);
603         JavaProxyConstructor.createJavaProxyConstructorClass(runtime,
604                 javaProxyModule);
605
606     }
607
608     public String JavaDoc nameOnInspection() {
609         return "[Proxy:" + getSuperclass().getName() + "]";
610     }
611
612     public IRubyObject define_instance_methods_for_proxy(IRubyObject arg) {
613         assert arg instanceof RubyClass;
614
615         Map JavaDoc aliasesClump = getPropertysClumped();
616         Map JavaDoc methodsClump = getMethodsClumped(false);
617         RubyClass proxy = (RubyClass) arg;
618
619         for (Iterator JavaDoc iter = methodsClump.keySet().iterator(); iter.hasNext();) {
620             String JavaDoc name = (String JavaDoc) iter.next();
621             RubyArray methods = (RubyArray) methodsClump.get(name);
622             List JavaDoc aliases = (List JavaDoc) aliasesClump.get(name);
623
624             if (aliases == null) {
625                 aliases = new ArrayList JavaDoc();
626             }
627
628             aliases.add(name);
629
630             define_instance_method_for_proxy(proxy, aliases, methods);
631         }
632
633         return getRuntime().getNil();
634     }
635
636     /**
637      * Get all methods grouped by name (e.g. 'new => {new(), new(int), new(int,
638      * int)}, ...')
639      *
640      * @param isStatic
641      * determines whether you want static or instance methods from
642      * the class
643      */

644     private Map JavaDoc getMethodsClumped(boolean isStatic) {
645         Map JavaDoc map = new HashMap JavaDoc();
646         JavaProxyMethod[] methods = getMethods();
647
648         for (int i = 0; i < methods.length; i++) {
649             if (isStatic != Modifier.isStatic(methods[i].getModifiers())) {
650                 continue;
651             }
652
653             String JavaDoc key = methods[i].getName();
654             RubyArray methodsWithName = (RubyArray) map.get(key);
655
656             if (methodsWithName == null) {
657                 methodsWithName = getRuntime().newArray();
658                 map.put(key, methodsWithName);
659             }
660
661             methodsWithName.append(methods[i]);
662         }
663
664         return map;
665     }
666
667     private Map JavaDoc getPropertysClumped() {
668         Map JavaDoc map = new HashMap JavaDoc();
669         BeanInfo JavaDoc info;
670
671         try {
672             info = Introspector.getBeanInfo(proxyClass);
673         } catch (IntrospectionException JavaDoc e) {
674             return map;
675         }
676
677         PropertyDescriptor JavaDoc[] descriptors = info.getPropertyDescriptors();
678
679         for (int i = 0; i < descriptors.length; i++) {
680             Method JavaDoc readMethod = descriptors[i].getReadMethod();
681
682             if (readMethod != null) {
683                 String JavaDoc key = readMethod.getName();
684                 List JavaDoc aliases = (List JavaDoc) map.get(key);
685
686                 if (aliases == null) {
687                     aliases = new ArrayList JavaDoc();
688
689                     map.put(key, aliases);
690                 }
691
692                 if (readMethod.getReturnType() == Boolean JavaDoc.class
693                         || readMethod.getReturnType() == boolean.class) {
694                     aliases.add(descriptors[i].getName() + "?");
695                 }
696                 aliases.add(descriptors[i].getName());
697             }
698
699             Method JavaDoc writeMethod = descriptors[i].getWriteMethod();
700
701             if (writeMethod != null) {
702                 String JavaDoc key = writeMethod.getName();
703                 List JavaDoc aliases = (List JavaDoc) map.get(key);
704
705                 if (aliases == null) {
706                     aliases = new ArrayList JavaDoc();
707                     map.put(key, aliases);
708                 }
709
710                 aliases.add(descriptors[i].getName() + "=");
711             }
712         }
713
714         return map;
715     }
716
717     private void define_instance_method_for_proxy(final RubyClass proxy,
718             List JavaDoc names, final RubyArray methods) {
719         final RubyModule javaUtilities = getRuntime()
720                 .getModule("JavaUtilities");
721         Callback method = new Callback() {
722                 public IRubyObject execute(IRubyObject self, IRubyObject[] args, Block block) {
723                 IRubyObject[] argsArray = new IRubyObject[args.length + 1];
724                 argsArray[0] = self.callMethod(getRuntime().getCurrentContext(),"java_object");
725                 RubyArray argsAsArray = getRuntime().newArray();
726                 for (int j = 0; j < args.length; j++) {
727                     argsArray[j + 1] = args[j];
728                     argsAsArray.append(Java.ruby_to_java(proxy, argsArray[j + 1], Block.NULL_BLOCK));
729                 }
730
731                 IRubyObject[] mmArgs = new IRubyObject[] { methods, argsAsArray };
732                 IRubyObject result = javaUtilities.callMethod(getRuntime().getCurrentContext(),
733                         "matching_method", mmArgs);
734                 return Java.java_to_ruby(self,
735                         result.callMethod(getRuntime().getCurrentContext(),"invoke", argsArray),
736                         Block.NULL_BLOCK);
737             }
738
739             public Arity getArity() {
740                 return Arity.optional();
741             }
742         };
743
744         for (Iterator JavaDoc iter = names.iterator(); iter.hasNext();) {
745             String JavaDoc methodName = (String JavaDoc) iter.next();
746
747             // We do not override class since it is too important to be
748
// overridden by getClass
749
// short name.
750
if (!methodName.equals("class")) {
751                 proxy.defineMethod(methodName, method);
752
753                 String JavaDoc rubyCasedName = JavaClass.getRubyCasedName(methodName);
754                 if (rubyCasedName != null) {
755                     proxy.defineAlias(rubyCasedName, methodName);
756                 }
757             }
758         }
759     }
760
761 }
762
Popular Tags