Block.NULL_BLOCK);
return setupJavaSubclass(tc, subclass, recv.callMethod(tc, "java_class"));
}
private static IRubyObject setupJavaSubclass(ThreadContext context, IRubyObject subclass, IRubyObject java_class) {
Ruby runtime = context.getRuntime();
if (!(subclass instanceof RubyClass)) {
throw runtime.newTypeError(subclass, runtime.getClassClass());
}
RubyClass rubySubclass = (RubyClass)subclass;
rubySubclass.getInstanceVariables().fastSetInstanceVariable("@java_proxy_class", runtime.getNil());
RubyClass subclassSingleton = rubySubclass.getSingletonClass();
subclassSingleton.addReadWriteAttribute(context, "java_proxy_class");
subclassSingleton.addMethod("java_interfaces", new JavaMethodZero(subclassSingleton, Visibility.PUBLIC) {
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name) {
IRubyObject javaInterfaces = self.getInstanceVariables().fastGetInstanceVariable("@java_interfaces");
if (javaInterfaces != null) return javaInterfaces.dup();
return context.getRuntime().getNil();
}
});
rubySubclass.addMethod("__jcreate!", new JavaMethodNoBlock(subclassSingleton, Visibility.PUBLIC) {
private final Map<Integer, ParameterTypes> methodCache = new HashMap<Integer, ParameterTypes>();
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject[] args) {
IRubyObject proxyClass = self.getMetaClass().getInstanceVariables().fastGetInstanceVariable("@java_proxy_class");
if (proxyClass == null || proxyClass.isNil()) {
proxyClass = JavaProxyClass.get_with_class(self, self.getMetaClass());
self.getMetaClass().getInstanceVariables().fastSetInstanceVariable("@java_proxy_class", proxyClass);
}
JavaProxyClass realProxyClass = (JavaProxyClass)proxyClass;
RubyArray constructors = realProxyClass.constructors();
ArrayList<JavaProxyConstructor> forArity = new ArrayList<JavaProxyConstructor>();
for (int i = 0; i < constructors.size(); i++) {
JavaProxyConstructor constructor = (JavaProxyConstructor)constructors.eltInternal(i);
if (constructor.getParameterTypes().length == args.length) {
forArity.add(constructor);
}
}
if (forArity.size() == 0) {
throw context.getRuntime().newArgumentError("wrong # of arguments for constructor");
}
JavaProxyConstructor matching = (JavaProxyConstructor)matchingCallableArityN(
self,
methodCache,
forArity.toArray(new JavaProxyConstructor[forArity.size()]), args, args.length);
Object[] newArgs = new Object[args.length];
Class[] parameterTypes = matching.getParameterTypes();
for (int i = 0; i < args.length; i++) {
newArgs[i] = JavaUtil.convertArgumentToType(context, args[i], parameterTypes[i]);
}
JavaObject newObject = matching.newInstance(self, newArgs);
return JavaUtilities.set_java_object(self, self, newObject);
}
});
return runtime.getNil();
}