Fix for JRUBY-2882. Handle error messages related to constructors better
[jruby.git] / src / org / jruby / javasupport / proxy / JavaProxyClass.java
blobdef55285b16c48006d5a672131ad7ef75c66c41b
1 /*
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;
45 import java.util.Map;
46 import java.util.Set;
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;
66 /**
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;
89 /* package scope */
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() {
108 return this;
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);
119 try {
120 ClassLoader loader = runtime.getJRubyClassLoader();
122 return JavaProxyClassFactory.newProxyClass(runtime, loader, null, superClass, interfaces, names);
123 } finally {
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];
153 int pos = 0;
154 for (int i = 0; i < ifaces.length; i++) {
155 if (ifaces[i] != InternalJavaProxy.class) {
156 result[pos++] = ifaces[i];
159 return result;
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]);
168 return result;
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;
194 return null;
197 /** return the class of instances of this proxy class */
198 Class getProxyClass() {
199 return proxyClass;
202 @Override
203 public Class getJavaClass() {
204 return proxyClass;
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,
220 Method sm) {
221 super(runtime, runtime.getJavaSupport().getJavaModule()
222 .fastGetClass("JavaProxyMethod"));
223 this.m = m;
224 this.parameterTypes = m.getParameterTypes();
225 this.sm = sm;
226 this.clazz = clazz;
229 public boolean equals(Object other) {
230 return other instanceof ProxyMethodImpl &&
231 this.m == ((ProxyMethodImpl)other).m;
234 public int hashCode() {
235 return m.hashCode();
238 public Method getMethod() {
239 return m;
242 public Method getSuperMethod() {
243 return sm;
246 public int getModifiers() {
247 return m.getModifiers();
250 public String getName() {
251 return m.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() {
267 return state;
270 public boolean hasSuperImplementation() {
271 return sm != null;
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) {
283 this.state = state;
286 public String toString() {
287 return m.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);
302 return null;
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);
321 return result;
324 public RubyObject name() {
325 return getRuntime().newString(getName());
328 @JRubyMethod(name = "declaring_class")
329 public JavaProxyClass getDeclaringClass() {
330 return clazz;
333 @JRubyMethod
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();
343 @JRubyMethod
344 public RubyFixnum arity() {
345 return getRuntime().newFixnum(getArity());
348 protected String nameOnInspection() {
349 return getDeclaringClass().nameOnInspection() + "/" + getName();
352 @JRubyMethod
353 public IRubyObject inspect() {
354 StringBuilder result = new StringBuilder();
355 result.append(nameOnInspection());
356 result.append("(");
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) {
361 result.append(',');
364 result.append(")>");
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++) {
384 arguments[i] =
385 JavaUtil.convertRubyToJava((IRubyObject) arguments[i], parameterTypes[i]);
388 try {
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() + "': " +
395 iae.getMessage());
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
400 // installed.
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;
413 try {
414 Class[] parms = parse(proxy.getClassLoader(), desc);
415 Method m = proxy.getDeclaredMethod(name, parms);
416 Method sm = null;
417 if (hasSuper) {
418 sm = proxy.getDeclaredMethod("__super$" + name, parms);
421 JavaProxyMethod jpm = new ProxyMethodImpl(getRuntime(), this, m, sm);
422 methods.add(jpm);
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);
430 return 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>();
443 int idx = 1;
444 while (desc.charAt(idx) != ')') {
446 int arr = 0;
447 while (desc.charAt(idx) == '[') {
448 idx += 1;
449 arr += 1;
452 Class type;
454 switch (desc.charAt(idx)) {
455 case 'L':
456 int semi = desc.indexOf(';', idx);
457 final String name = desc.substring(idx + 1, semi);
458 idx = semi;
459 try {
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();
468 break;
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;
478 default:
479 throw new InternalError("cannot parse " + desc + "[" + idx + "]");
482 idx += 1;
484 if (arr != 0) {
485 type = Array.newInstance(type, new int[arr]).getClass();
488 al.add(type);
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);
506 return result;
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;
516 try {
517 return getProxyClass(recv.getRuntime(), (Class) type.getValue(), new Class[0]);
518 } catch (Error e) {
519 RaiseException ex = recv.getRuntime().newArgumentError("unable to create proxy class for " + type.getValue());
520 ex.initCause(e);
521 throw ex;
522 } catch (InvocationTargetException e) {
523 RaiseException ex = recv.getRuntime().newArgumentError("unable to create proxy class for " + type.getValue());
524 ex.initCause(e);
525 throw ex;
529 private static final HashSet<String> EXCLUDE_MODULES = new HashSet<String>();
530 static {
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>();
538 static {
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;
580 continue;
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");
586 if (var == null) {
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 +
600 " (" + var + ")");
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");
637 if (var == null) {
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);
652 } else {
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);
692 try {
693 return getProxyClass(recv.getRuntime(), javaClass.javaClass(), interfaces, names);
694 } catch (Error e) {
695 RaiseException ex = recv.getRuntime().newArgumentError("unable to create proxy class for " + javaClass.getValue() + " : " + e.getMessage());
696 //e.printStackTrace();
697 ex.initCause(e);
698 throw ex;
699 } catch (InvocationTargetException e) {
700 RaiseException ex = recv.getRuntime().newArgumentError("unable to create proxy class for " + javaClass.getValue() + " : " + e.getMessage());
701 //e.printStackTrace();
702 ex.initCause(e);
703 throw ex;
707 @JRubyMethod
708 public RubyObject superclass() {
709 return JavaClass.get(getRuntime(), getSuperclass());
712 @JRubyMethod
713 public RubyArray methods() {
714 return buildRubyArray(getMethods());
717 @JRubyMethod
718 public RubyArray interfaces() {
719 return buildRubyArray(getInterfaces());
722 @JRubyMethod
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() + "]";