package org.jruby.java.proxies;
import org.jruby.Ruby;
import org.jruby.RubyClass;
import org.jruby.RubyModule;
import org.jruby.internal.runtime.methods.DynamicMethod;
import org.jruby.javasupport.Java;
import org.jruby.runtime.Block;
import org.jruby.runtime.CallSite;
import org.jruby.runtime.MethodIndex;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.Visibility;
import org.jruby.runtime.builtin.IRubyObject;
public class ConcreteJavaProxy extends JavaProxy {
public ConcreteJavaProxy(Ruby runtime, RubyClass klazz) {
super(runtime, klazz);
}
public ConcreteJavaProxy(Ruby runtime, RubyClass klazz, Object object) {
super(runtime, klazz, object);
}
private static final ObjectAllocator ALLOCATOR = new ObjectAllocator() {
public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
return new ConcreteJavaProxy(runtime, klazz);
}
};
public static RubyClass createConcreteJavaProxy(final ThreadContext context) {
final Ruby runtime = context.runtime;
final RubyClass JavaProxy = runtime.getJavaSupport().getJavaProxyClass();
RubyClass ConcreteJavaProxy = runtime.defineClass("ConcreteJavaProxy", JavaProxy, ALLOCATOR);
initialize(ConcreteJavaProxy);
return ConcreteJavaProxy;
}
private static final class InitializeMethod extends org.jruby.internal.runtime.methods.JavaMethod {
private final CallSite jcreateSite = MethodIndex.getFunctionalCallSite("__jcreate!");
InitializeMethod(final RubyClass clazz) { super(clazz, Visibility.PRIVATE, "initialize"); }
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject[] args, Block block) {
return jcreateSite.call(context, self, self, args, block);
}
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, Block block) {
return jcreateSite.call(context, self, self, block);
}
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, Block block) {
return jcreateSite.call(context, self, self, arg0, block);
}
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1, Block block) {
return jcreateSite.call(context, self, self, arg0, arg1, block);
}
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block) {
return jcreateSite.call(context, self, self, arg0, arg1, arg2, block);
}
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject[] args) {
return jcreateSite.call(context, self, self, args);
}
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name) {
return jcreateSite.call(context, self, self);
}
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0) {
return jcreateSite.call(context, self, self, arg0);
}
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1) {
return jcreateSite.call(context, self, self, arg0, arg1);
}
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2) {
return jcreateSite.call(context, self, self, arg0, arg1, arg2);
}
}
private static final class NewMethod extends org.jruby.internal.runtime.methods.JavaMethod {
private transient CallSite jcreateSite;
final DynamicMethod newMethod;
NewMethod(final RubyClass clazz) {
super(clazz, Visibility.PUBLIC, "new");
newMethod = clazz.searchMethod("new");
}
private CallSite jcreateSite() {
CallSite callSite = jcreateSite;
if (callSite == null) {
callSite = jcreateSite = MethodIndex.getFunctionalCallSite("__jcreate!");
}
return callSite;
}
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject[] args, Block block) {
IRubyObject proxy = newMethod.call(context, self, clazz, "new_proxy", args, block);
if ( ((JavaProxy) proxy).object == null ) jcreateSite().call(context, proxy, proxy, args, block);
return proxy;
}
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, Block block) {
IRubyObject proxy = newMethod.call(context, self, clazz, "new_proxy", block);
if ( ((JavaProxy) proxy).object == null ) jcreateSite().call(context, proxy, proxy, block);
return proxy;
}
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, Block block) {
IRubyObject proxy = newMethod.call(context, self, clazz, "new_proxy", arg0, block);
if ( ((JavaProxy) proxy).object == null ) jcreateSite().call(context, proxy, proxy, arg0, block);
return proxy;
}
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1, Block block) {
IRubyObject proxy = newMethod.call(context, self, clazz, "new_proxy", arg0, arg1, block);
if ( ((JavaProxy) proxy).object == null ) jcreateSite().call(context, proxy, proxy, arg0, arg1, block);
return proxy;
}
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block) {
IRubyObject proxy = newMethod.call(context, self, clazz, "new_proxy", arg0, arg1, arg2, block);
if ( ((JavaProxy) proxy).object == null ) jcreateSite().call(context, proxy, proxy, arg0, arg1, arg2, block);
return proxy;
}
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject[] args) {
IRubyObject proxy = newMethod.call(context, self, clazz, "new_proxy", args);
if ( ((JavaProxy) proxy).object == null ) jcreateSite().call(context, proxy, proxy, args);
return proxy;
}
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name) {
IRubyObject proxy = newMethod.call(context, self, clazz, "new_proxy");
if ( ((JavaProxy) proxy).object == null ) jcreateSite().call(context, proxy, proxy);
return proxy;
}
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0) {
IRubyObject proxy = newMethod.call(context, self, clazz, "new_proxy", arg0);
if ( ((JavaProxy) proxy).object == null ) jcreateSite().call(context, proxy, proxy, arg0);
return proxy;
}
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1) {
IRubyObject proxy = newMethod.call(context, self, clazz, "new_proxy", arg0, arg1);
if ( ((JavaProxy) proxy).object == null ) jcreateSite().call(context, proxy, proxy, arg0, arg1);
return proxy;
}
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2) {
IRubyObject proxy = newMethod.call(context, self, clazz, "new_proxy", arg0, arg1, arg2);
if ( ((JavaProxy) proxy).object == null ) jcreateSite().call(context, proxy, proxy, arg0, arg1, arg2);
return proxy;
}
}
protected static void initialize(final RubyClass ConcreteJavaProxy) {
ConcreteJavaProxy.addMethod("initialize", new InitializeMethod(ConcreteJavaProxy));
RubyClass singleton = ConcreteJavaProxy.getSingletonClass();
singleton.addMethod("new", new NewMethod(singleton));
}
@Override
public IRubyObject id() {
return getRuntime().newFixnum(System.identityHashCode(getObject()));
}
@Override
@SuppressWarnings("unchecked")
public <T> T toJava(Class<T> type) {
final Object object = getObject();
final Class clazz = object.getClass();
if ( type.isPrimitive() ) {
if ( type == Void.TYPE ) return null;
if ( object instanceof Number && type != Boolean.TYPE ||
object instanceof Character && type == Character.TYPE ||
object instanceof Boolean && type == Boolean.TYPE ) {
return (T) object;
}
}
else if ( type.isAssignableFrom(clazz) ) {
if ( Java.OBJECT_PROXY_CACHE || metaClass.getCacheProxy() ) {
getRuntime().getJavaSupport().getObjectProxyCache().put(object, this);
}
return type.cast(object);
}
else if ( type.isAssignableFrom(getClass()) ) return type.cast(this);
throw getRuntime().newTypeError("failed to coerce " + clazz.getName() + " to " + type.getName());
}
}