2 ***** BEGIN LICENSE BLOCK *****
3 * Version: CPL 1.0/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Common Public
6 * License Version 1.0 (the "License"); you may not use this file
7 * except in compliance with the License. You may obtain a copy of
8 * the License at http://www.eclipse.org/legal/cpl-v10.html
10 * Software distributed under the License is distributed on an "AS
11 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
12 * implied. See the License for the specific language governing
13 * rights and limitations under the License.
15 * Copyright (C) 2006 Kresten Krab Thorup <krab@gnu.org>
16 * Copyright (C) 2007 William N Dortch <bill.dortch@gmail.com>
18 * Alternatively, the contents of this file may be used under the terms of
19 * either of the GNU General Public License Version 2 or later (the "GPL"),
20 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
21 * in which case the provisions of the GPL or the LGPL are applicable instead
22 * of those above. If you wish to allow use of your version of this file only
23 * under the terms of either the GPL or the LGPL, and not to allow others to
24 * use your version of this file under the terms of the CPL, indicate your
25 * decision by deleting the provisions above and replace them with the notice
26 * and other provisions required by the GPL or the LGPL. If you do not delete
27 * the provisions above, a recipient may use your version of this file under
28 * the terms of any one of the CPL, the GPL or the LGPL.
29 ***** END LICENSE BLOCK *****/
31 package org
.jruby
.javasupport
.proxy
;
33 import java
.lang
.reflect
.Array
;
34 import java
.lang
.reflect
.Constructor
;
35 import java
.lang
.reflect
.InvocationTargetException
;
36 import java
.lang
.reflect
.Method
;
37 import java
.security
.AccessController
;
38 import java
.security
.PrivilegedActionException
;
39 import java
.security
.PrivilegedExceptionAction
;
40 import java
.util
.ArrayList
;
41 import java
.util
.Arrays
;
42 import java
.util
.HashMap
;
43 import java
.util
.HashSet
;
44 import java
.util
.List
;
48 import org
.jruby
.Ruby
;
49 import org
.jruby
.RubyArray
;
50 import org
.jruby
.RubyClass
;
51 import org
.jruby
.RubyFixnum
;
52 import org
.jruby
.RubyModule
;
53 import org
.jruby
.RubyObject
;
54 import org
.jruby
.RubyNil
;
55 import org
.jruby
.RubyString
;
56 import org
.jruby
.anno
.JRubyClass
;
57 import org
.jruby
.anno
.JRubyMethod
;
58 import org
.jruby
.exceptions
.RaiseException
;
59 import org
.jruby
.internal
.runtime
.methods
.DynamicMethod
;
60 import org
.jruby
.javasupport
.JavaClass
;
61 import org
.jruby
.javasupport
.JavaObject
;
62 import org
.jruby
.javasupport
.JavaUtil
;
63 import org
.jruby
.runtime
.ObjectAllocator
;
64 import org
.jruby
.runtime
.builtin
.IRubyObject
;
67 * Generalized proxy for classes and interfaces.
69 * API looks a lot like java.lang.reflect.Proxy, except that you can specify a
70 * super class in addition to a set of interfaces.
72 * The main implication for users of this class is to handle the case where a
73 * proxy method overrides an existing method, because in this case the
74 * invocation handler should "default" to calling the super implementation
75 * {JavaProxyMethod.invokeSuper}.
78 * @author krab@trifork.com
79 * @see java.lang.reflect.Proxy
82 public class JavaProxyClass
extends JavaProxyReflectionObject
{
83 static ThreadLocal
<Ruby
> runtimeTLS
= new ThreadLocal
<Ruby
>();
84 private final Class proxyClass
;
85 private final ArrayList
<JavaProxyMethod
> methods
= new ArrayList
<JavaProxyMethod
>();
86 private final HashMap
<String
, List
<JavaProxyMethod
>> methodMap
= new HashMap
<String
, List
<JavaProxyMethod
>>();
87 private final RubyArray constructors
;
90 JavaProxyClass(Class proxyClass
) {
91 super(getThreadLocalRuntime(),
92 (RubyClass
) getThreadLocalRuntime().fastGetModule("Java").fastGetClass("JavaProxyClass"));
94 this.proxyClass
= proxyClass
;
95 this.constructors
= buildRubyArray(getConstructors());
98 public boolean equals(Object other
) {
99 return other
instanceof JavaProxyClass
&&
100 this.proxyClass
== ((JavaProxyClass
)other
).proxyClass
;
103 public int hashCode() {
104 return proxyClass
.hashCode();
107 public Object
getValue() {
111 private static Ruby
getThreadLocalRuntime() {
112 return runtimeTLS
.get();
115 public static JavaProxyClass
getProxyClass(Ruby runtime
, Class superClass
,
116 Class
[] interfaces
, Set names
) throws InvocationTargetException
{
117 Ruby save
= runtimeTLS
.get();
118 runtimeTLS
.set(runtime
);
120 ClassLoader loader
= runtime
.getJRubyClassLoader();
122 return JavaProxyClassFactory
.newProxyClass(runtime
, loader
, null, superClass
, interfaces
, names
);
124 runtimeTLS
.set(save
);
128 public static JavaProxyClass
getProxyClass(Ruby runtime
, Class superClass
,
129 Class
[] interfaces
) throws InvocationTargetException
{
130 return getProxyClass(runtime
,superClass
,interfaces
,null);
133 public static Object
newProxyInstance(Ruby runtime
, Class superClass
, Class
[] interfaces
,
134 Class
[] constructorParameters
, Object
[] constructorArgs
,
135 JavaProxyInvocationHandler handler
) throws IllegalArgumentException
,
136 InstantiationException
, IllegalAccessException
, InvocationTargetException
,
137 SecurityException
, NoSuchMethodException
{
138 JavaProxyClass jpc
= getProxyClass(runtime
, superClass
, interfaces
);
139 JavaProxyConstructor cons
= jpc
.getConstructor(constructorParameters
== null ?
140 new Class
[0] : constructorParameters
);
142 return cons
.newInstance(constructorArgs
, handler
);
146 public Class
getSuperclass() {
147 return proxyClass
.getSuperclass();
150 public Class
[] getInterfaces() {
151 Class
[] ifaces
= proxyClass
.getInterfaces();
152 Class
[] result
= new Class
[ifaces
.length
- 1];
154 for (int i
= 0; i
< ifaces
.length
; i
++) {
155 if (ifaces
[i
] != InternalJavaProxy
.class) {
156 result
[pos
++] = ifaces
[i
];
162 public JavaProxyConstructor
[] getConstructors() {
163 Constructor
[] cons
= proxyClass
.getConstructors();
164 JavaProxyConstructor
[] result
= new JavaProxyConstructor
[cons
.length
];
165 for (int i
= 0; i
< cons
.length
; i
++) {
166 result
[i
] = new JavaProxyConstructor(getRuntime(), this, cons
[i
]);
171 public JavaProxyConstructor
getConstructor(Class
[] args
)
172 throws SecurityException
, NoSuchMethodException
{
174 Class
[] realArgs
= new Class
[args
.length
+ 1];
175 System
.arraycopy(args
, 0, realArgs
, 0, args
.length
);
176 realArgs
[args
.length
] = JavaProxyInvocationHandler
.class;
178 Constructor constructor
= proxyClass
.getConstructor(realArgs
);
179 return new JavaProxyConstructor(getRuntime(), this, constructor
);
182 public JavaProxyMethod
[] getMethods() {
183 return methods
.toArray(new JavaProxyMethod
[methods
.size()]);
186 public JavaProxyMethod
getMethod(String name
, Class
[] parameterTypes
) {
187 List
<JavaProxyMethod
> methods
= methodMap
.get(name
);
188 if (methods
!= null) {
189 for (int i
= methods
.size(); --i
>= 0; ) {
190 ProxyMethodImpl jpm
= (ProxyMethodImpl
) methods
.get(i
);
191 if (jpm
.matches(name
, parameterTypes
)) return jpm
;
197 /** return the class of instances of this proxy class */
198 Class
getProxyClass() {
203 public Class
getJavaClass() {
207 @JRubyClass(name
="JavaProxy::JavaProxyMethod")
208 public static class ProxyMethodImpl
extends JavaProxyReflectionObject
209 implements JavaProxyMethod
{
210 private final Method m
;
212 private Object state
;
214 private final Method sm
;
215 private final Class
[] parameterTypes
;
217 private final JavaProxyClass clazz
;
219 public ProxyMethodImpl(Ruby runtime
, JavaProxyClass clazz
, Method m
,
221 super(runtime
, runtime
.getJavaSupport().getJavaModule()
222 .fastGetClass("JavaProxyMethod"));
224 this.parameterTypes
= m
.getParameterTypes();
229 public boolean equals(Object other
) {
230 return other
instanceof ProxyMethodImpl
&&
231 this.m
== ((ProxyMethodImpl
)other
).m
;
234 public int hashCode() {
238 public Method
getMethod() {
242 public Method
getSuperMethod() {
246 public int getModifiers() {
247 return m
.getModifiers();
250 public String
getName() {
254 public Class
<?
>[] getExceptionTypes() {
255 return m
.getExceptionTypes();
258 public Class
<?
>[] getParameterTypes() {
259 return parameterTypes
;
262 public boolean isVarArgs() {
263 return m
.isVarArgs();
266 public Object
getState() {
270 public boolean hasSuperImplementation() {
274 public Object
invoke(Object proxy
, Object
[] args
) throws IllegalArgumentException
,
275 IllegalAccessException
, InvocationTargetException
, NoSuchMethodException
{
277 if (!hasSuperImplementation()) throw new NoSuchMethodException();
279 return sm
.invoke(proxy
, args
);
282 public void setState(Object state
) {
286 public String
toString() {
290 public Object
defaultResult() {
291 Class rt
= m
.getReturnType();
293 if (rt
== Void
.TYPE
) return null;
294 if (rt
== Boolean
.TYPE
) return Boolean
.FALSE
;
295 if (rt
== Byte
.TYPE
) return new Byte((byte) 0);
296 if (rt
== Short
.TYPE
) return new Short((short) 0);
297 if (rt
== Integer
.TYPE
) return new Integer(0);
298 if (rt
== Long
.TYPE
) return new Long(0L);
299 if (rt
== Float
.TYPE
) return new Float(0.0f
);
300 if (rt
== Double
.TYPE
) return new Double(0.0);
305 public boolean matches(String name
, Class
[] parameterTypes
) {
306 return m
.getName().equals(name
) && Arrays
.equals(this.parameterTypes
, parameterTypes
);
309 public Class
getReturnType() {
310 return m
.getReturnType();
313 public static RubyClass
createJavaProxyMethodClass(Ruby runtime
, RubyModule javaProxyModule
) {
314 RubyClass result
= javaProxyModule
.defineClassUnder("JavaProxyMethod",
315 runtime
.getObject(), ObjectAllocator
.NOT_ALLOCATABLE_ALLOCATOR
);
317 JavaProxyReflectionObject
.registerRubyMethods(runtime
, result
);
319 result
.defineAnnotatedMethods(ProxyMethodImpl
.class);
324 public RubyObject
name() {
325 return getRuntime().newString(getName());
328 @JRubyMethod(name
= "declaring_class")
329 public JavaProxyClass
getDeclaringClass() {
334 public RubyArray
argument_types() {
335 return buildRubyArray(getParameterTypes());
338 @JRubyMethod(name
= "super?")
339 public IRubyObject
super_p() {
340 return hasSuperImplementation() ?
getRuntime().getTrue() : getRuntime().getFalse();
344 public RubyFixnum
arity() {
345 return getRuntime().newFixnum(getArity());
348 protected String
nameOnInspection() {
349 return getDeclaringClass().nameOnInspection() + "/" + getName();
353 public IRubyObject
inspect() {
354 StringBuilder result
= new StringBuilder();
355 result
.append(nameOnInspection());
357 Class
[] parameterTypes
= getParameterTypes();
358 for (int i
= 0; i
< parameterTypes
.length
; i
++) {
359 result
.append(parameterTypes
[i
].getName());
360 if (i
< parameterTypes
.length
- 1) {
365 return getRuntime().newString(result
.toString());
368 @JRubyMethod(name
= "invoke", rest
= true)
369 public IRubyObject
do_invoke(IRubyObject
[] nargs
) {
370 if (nargs
.length
!= 1 + getArity()) {
371 throw getRuntime().newArgumentError(nargs
.length
, 1 + getArity());
374 IRubyObject invokee
= nargs
[0];
375 if (!(invokee
instanceof JavaObject
)) {
376 throw getRuntime().newTypeError("invokee not a java object");
378 Object receiver_value
= ((JavaObject
) invokee
).getValue();
379 Object
[] arguments
= new Object
[nargs
.length
- 1];
380 System
.arraycopy(nargs
, 1, arguments
, 0, arguments
.length
);
382 Class
[] parameterTypes
= getParameterTypes();
383 for (int i
= 0; i
< arguments
.length
; i
++) {
385 JavaUtil
.convertRubyToJava((IRubyObject
) arguments
[i
], parameterTypes
[i
]);
389 Object javaResult
= sm
.invoke(receiver_value
, arguments
);
390 return JavaUtil
.convertJavaToRuby(getRuntime(), javaResult
, getReturnType());
391 } catch (IllegalArgumentException e
) {
392 throw getRuntime().newTypeError("expected " + argument_types().inspect());
393 } catch (IllegalAccessException iae
) {
394 throw getRuntime().newTypeError("illegal access on '" + sm
.getName() + "': " +
396 } catch (InvocationTargetException ite
) {
397 if (getRuntime().getDebug().isTrue()) ite
.getTargetException().printStackTrace();
398 getRuntime().getJavaSupport().handleNativeException(ite
.getTargetException());
399 // This point is only reached if there was an exception handler
401 return getRuntime().getNil();
405 private int getArity() {
406 return getParameterTypes().length
;
411 JavaProxyMethod
initMethod(String name
, String desc
, boolean hasSuper
) {
412 Class proxy
= proxyClass
;
414 Class
[] parms
= parse(proxy
.getClassLoader(), desc
);
415 Method m
= proxy
.getDeclaredMethod(name
, parms
);
418 sm
= proxy
.getDeclaredMethod("__super$" + name
, parms
);
421 JavaProxyMethod jpm
= new ProxyMethodImpl(getRuntime(), this, m
, sm
);
423 List
<JavaProxyMethod
> methodsWithName
= methodMap
.get(name
);
424 if (methodsWithName
== null) {
425 methodsWithName
= new ArrayList
<JavaProxyMethod
>(2);
426 methodMap
.put(name
,methodsWithName
);
428 methodsWithName
.add(jpm
);
431 } catch (ClassNotFoundException e
) {
432 throw new InternalError(e
.getMessage());
433 } catch (SecurityException e
) {
434 throw new InternalError(e
.getMessage());
435 } catch (NoSuchMethodException e
) {
436 throw new InternalError(e
.getMessage());
440 private static Class
[] parse(final ClassLoader loader
, String desc
)
441 throws ClassNotFoundException
{
442 List
<Class
> al
= new ArrayList
<Class
>();
444 while (desc
.charAt(idx
) != ')') {
447 while (desc
.charAt(idx
) == '[') {
454 switch (desc
.charAt(idx
)) {
456 int semi
= desc
.indexOf(';', idx
);
457 final String name
= desc
.substring(idx
+ 1, semi
);
460 type
= AccessController
.doPrivileged(new PrivilegedExceptionAction
<Class
>() {
461 public Class
run() throws ClassNotFoundException
{
462 return Class
.forName(name
.replace('/', '.'), false, loader
);
465 } catch (PrivilegedActionException e
) {
466 throw (ClassNotFoundException
) e
.getException();
470 case 'B': type
= Byte
.TYPE
; break;
471 case 'C': type
= Character
.TYPE
; break;
472 case 'Z': type
= Boolean
.TYPE
; break;
473 case 'S': type
= Short
.TYPE
; break;
474 case 'I': type
= Integer
.TYPE
; break;
475 case 'J': type
= Long
.TYPE
; break;
476 case 'F': type
= Float
.TYPE
; break;
477 case 'D': type
= Double
.TYPE
; break;
479 throw new InternalError("cannot parse " + desc
+ "[" + idx
+ "]");
485 type
= Array
.newInstance(type
, new int[arr
]).getClass();
491 return (Class
[]) al
.toArray(new Class
[al
.size()]);
495 // Ruby-level methods
498 public static RubyClass
createJavaProxyClassClass(Ruby runtime
, RubyModule javaModule
) {
499 RubyClass result
= javaModule
.defineClassUnder("JavaProxyClass",
500 runtime
.getObject(),ObjectAllocator
.NOT_ALLOCATABLE_ALLOCATOR
);
502 JavaProxyReflectionObject
.registerRubyMethods(runtime
, result
);
504 result
.defineAnnotatedMethods(JavaProxyClass
.class);
509 @JRubyMethod(meta
= true)
510 public static RubyObject
get(IRubyObject recv
, IRubyObject obj
) {
511 if (!(obj
instanceof JavaClass
)) {
512 throw recv
.getRuntime().newTypeError(obj
, recv
.getRuntime().getJavaSupport().getJavaClassClass());
514 JavaClass type
= (JavaClass
)obj
;
517 return getProxyClass(recv
.getRuntime(), (Class
) type
.getValue(), new Class
[0]);
519 RaiseException ex
= recv
.getRuntime().newArgumentError("unable to create proxy class for " + type
.getValue());
522 } catch (InvocationTargetException e
) {
523 RaiseException ex
= recv
.getRuntime().newArgumentError("unable to create proxy class for " + type
.getValue());
529 private static final HashSet
<String
> EXCLUDE_MODULES
= new HashSet
<String
>();
531 EXCLUDE_MODULES
.add("Kernel");
532 EXCLUDE_MODULES
.add("Java");
533 EXCLUDE_MODULES
.add("JavaProxyMethods");
534 EXCLUDE_MODULES
.add("Enumerable");
537 private static final HashSet
<String
> EXCLUDE_METHODS
= new HashSet
<String
>();
539 EXCLUDE_METHODS
.add("class");
540 EXCLUDE_METHODS
.add("finalize");
541 EXCLUDE_METHODS
.add("initialize");
542 EXCLUDE_METHODS
.add("java_class");
543 EXCLUDE_METHODS
.add("java_object");
544 EXCLUDE_METHODS
.add("__jcreate!");
545 EXCLUDE_METHODS
.add("__jsend!");
548 @JRubyMethod(meta
= true)
549 public static RubyObject
get_with_class(IRubyObject recv
, IRubyObject obj
) {
550 Ruby runtime
= recv
.getRuntime();
552 if (!(obj
instanceof RubyClass
)) {
553 throw runtime
.newTypeError(obj
, runtime
.getClassClass());
556 RubyClass clazz
= (RubyClass
)obj
;
558 // Let's only generate methods for those the user may actually
559 // intend to override. That includes any defined in the current
560 // class, and any ancestors that are also JavaProxyClasses (but none
561 // from any other ancestor classes). Methods defined in mixins will
562 // be considered intentionally overridden, except those from Kernel,
563 // Java, and JavaProxyMethods, as well as Enumerable.
564 // TODO: may want to exclude other common mixins?
566 JavaClass javaClass
= null;
567 Set
<String
> names
= new HashSet
<String
>(); // need names ordered for key generation later
568 List
<Class
<?
>> interfaceList
= new ArrayList
<Class
<?
>>();
570 List
<IRubyObject
> ancestors
= clazz
.getAncestorList();
571 boolean skipRemainingClasses
= false;
572 for (IRubyObject ancestorObject
: ancestors
) {
573 RubyModule ancestor
= (RubyModule
) ancestorObject
;
574 if (ancestor
instanceof RubyClass
) {
575 if (skipRemainingClasses
) continue;
576 // we only collect methods and interfaces for
577 // user-defined proxy classes.
578 if (!ancestor
.getInstanceVariables().fastHasInstanceVariable("@java_proxy_class")) {
579 skipRemainingClasses
= true;
583 // get JavaClass if this is the new proxy class; verify it
584 // matches if this is a superclass proxy.
585 IRubyObject var
= ancestor
.getInstanceVariables().fastGetInstanceVariable("@java_class");
587 throw runtime
.newTypeError(
588 "no java_class defined for proxy (or ancestor): " + ancestor
);
589 } else if (!(var
instanceof JavaClass
)) {
590 throw runtime
.newTypeError(
591 "invalid java_class defined for proxy (or ancestor): " +
592 ancestor
+ ": " + var
);
594 if (javaClass
== null) {
595 javaClass
= (JavaClass
)var
;
596 } else if (javaClass
!= var
) {
597 throw runtime
.newTypeError(
598 "java_class defined for " + clazz
+ " (" + javaClass
+
599 ") does not match java_class for ancestor " + ancestor
+
602 // get any included interfaces
603 var
= ancestor
.getInstanceVariables().fastGetInstanceVariable("@java_interfaces");
604 if (var
!= null && !(var
instanceof RubyNil
)) {
605 if (!(var
instanceof RubyArray
)) {
606 throw runtime
.newTypeError(
607 "invalid java_interfaces defined for proxy (or ancestor): " +
608 ancestor
+ ": " + var
);
610 RubyArray ifcArray
= (RubyArray
)var
;
611 int size
= ifcArray
.size();
612 for (int i
= size
; --i
>= 0; ) {
613 IRubyObject ifc
= ifcArray
.eltInternal(i
);
614 if (!(ifc
instanceof JavaClass
)) {
615 throw runtime
.newTypeError(
616 "invalid java interface defined for proxy (or ancestor): " +
617 ancestor
+ ": " + ifc
);
619 Class interfaceClass
= ((JavaClass
)ifc
).javaClass();
620 if (!interfaceClass
.isInterface()) {
621 throw runtime
.newTypeError(
622 "invalid java interface defined for proxy (or ancestor): " +
623 ancestor
+ ": " + ifc
+ " (not an interface)");
625 if (!interfaceList
.contains(interfaceClass
)) {
626 interfaceList
.add(interfaceClass
);
630 // set this class's method names in var @__java_ovrd_methods if this
631 // is the new class; otherwise, get method names from there if this is
632 // a proxy superclass.
634 // FIXME: shouldn't need @__java_ovrd_methods, just query locally defined methods.
636 var
= ancestor
.getInstanceVariables().fastGetInstanceVariable("@__java_ovrd_methods");
638 // lock in the overridden methods for the new class, and any as-yet
639 // uninstantiated ancestor class.
640 Map
<String
, DynamicMethod
> methods
;
641 RubyArray methodNames
;
642 synchronized(methods
= ancestor
.getMethods()) {
643 methodNames
= RubyArray
.newArrayLight(runtime
,methods
.size());
644 for (String methodName
: methods
.keySet()) {
645 if (!EXCLUDE_METHODS
.contains(methodName
)) {
646 names
.add(methodName
);
647 methodNames
.append(runtime
.newString(methodName
));
651 ancestor
.fastSetInstanceVariable("@__java_ovrd_methods",methodNames
);
653 if (!(var
instanceof RubyArray
)) {
654 throw runtime
.newTypeError(
655 "invalid @__java_ovrd_methods defined for proxy: " +
656 ancestor
+ ": " + var
);
658 RubyArray methodNames
= (RubyArray
)var
;
659 int size
= methodNames
.size();
660 for (int i
= size
; --i
>= 0; ) {
661 IRubyObject methodName
= methodNames
.eltInternal(i
);
662 if (!(methodName
instanceof RubyString
)) {
663 throw runtime
.newTypeError(
664 "invalid method name defined for proxy (or ancestor): " +
665 ancestor
+ ": " + methodName
);
667 names
.add(methodName
.asJavaString());
670 } else if (!EXCLUDE_MODULES
.contains(ancestor
.getName())) {
671 Map
<String
, DynamicMethod
> methods
;
672 synchronized(methods
= ancestor
.getMethods()) {
673 for (String methodName
: methods
.keySet()) {
674 if (!EXCLUDE_METHODS
.contains(methodName
)) {
675 names
.add(methodName
);
682 if (javaClass
== null) {
683 throw runtime
.newArgumentError("unable to create proxy class: no java_class defined for " + clazz
);
686 int interfaceCount
= interfaceList
.size();
687 Class
<?
>[] interfaces
= new Class
<?
>[interfaceCount
];
688 for (int i
= interfaceCount
; --i
>= 0; ) {
689 interfaces
[i
] = interfaceList
.get(i
);
693 return getProxyClass(recv
.getRuntime(), javaClass
.javaClass(), interfaces
, names
);
695 RaiseException ex
= recv
.getRuntime().newArgumentError("unable to create proxy class for " + javaClass
.getValue() + " : " + e
.getMessage());
696 //e.printStackTrace();
699 } catch (InvocationTargetException e
) {
700 RaiseException ex
= recv
.getRuntime().newArgumentError("unable to create proxy class for " + javaClass
.getValue() + " : " + e
.getMessage());
701 //e.printStackTrace();
708 public RubyObject
superclass() {
709 return JavaClass
.get(getRuntime(), getSuperclass());
713 public RubyArray
methods() {
714 return buildRubyArray(getMethods());
718 public RubyArray
interfaces() {
719 return buildRubyArray(getInterfaces());
723 public RubyArray
constructors() {
724 return this.constructors
;
727 public static void createJavaProxyModule(Ruby runtime
) {
728 // TODO Auto-generated method stub
730 RubyModule javaProxyModule
= runtime
.getJavaSupport().getJavaModule();
731 JavaProxyClass
.createJavaProxyClassClass(runtime
, javaProxyModule
);
732 ProxyMethodImpl
.createJavaProxyMethodClass(runtime
, javaProxyModule
);
733 JavaProxyConstructor
.createJavaProxyConstructorClass(runtime
, javaProxyModule
);
736 public String
nameOnInspection() {
737 return "[Proxy:" + getSuperclass().getName() + "]";