Skip to content

Commit

Permalink
Add java_send, to allow calling a specific signature from Ruby withou…
Browse files Browse the repository at this point in the history
…t going through JavaClass/JavaMethod nonsense. No specs yet.
  • Loading branch information
headius committed Sep 27, 2009
1 parent 7381ba0 commit b5c0f19
Showing 1 changed file with 85 additions and 0 deletions.
85 changes: 85 additions & 0 deletions src/org/jruby/java/proxies/JavaProxy.java
@@ -1,27 +1,35 @@
package org.jruby.java.proxies;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.jruby.Ruby;
import org.jruby.RubyArray;
import org.jruby.RubyClass;
import org.jruby.RubyHash;
import org.jruby.RubyHash.Visitor;
import org.jruby.RubyModule;
import org.jruby.RubyObject;
import org.jruby.anno.JRubyMethod;
import org.jruby.java.addons.ArrayJavaAddons;
import org.jruby.java.invokers.InstanceFieldGetter;
import org.jruby.java.invokers.InstanceFieldSetter;
import org.jruby.javasupport.Java;
import org.jruby.javasupport.JavaClass;
import org.jruby.javasupport.JavaMethod;
import org.jruby.javasupport.JavaObject;
import org.jruby.javasupport.JavaUtil;
import org.jruby.javasupport.util.RuntimeHelpers;
import org.jruby.runtime.Arity;
import org.jruby.runtime.Block;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.CodegenUtils;

public class JavaProxy extends RubyObject {
protected final RubyClass.VariableAccessor objectAccessor;
Expand All @@ -47,6 +55,10 @@ public Object getObject() {
if (object == null) object = ((JavaObject)dataGetStruct()).getValue();
return object;
}

private JavaObject getJavaObject() {
return (JavaObject)dataGetStruct();
}

public static RubyClass createJavaProxy(ThreadContext context) {
Ruby runtime = context.getRuntime();
Expand Down Expand Up @@ -216,6 +228,79 @@ public IRubyObject equal_p(ThreadContext context, IRubyObject other) {
return runtime.getFalse();
}

@JRubyMethod
public IRubyObject java_send(ThreadContext context, IRubyObject rubyName) {
Class jclass = getJavaObject().getJavaClass();
String name = rubyName.asJavaString();
Ruby runtime = context.getRuntime();

try {
Method jmethod = jclass.getMethod(name);
JavaMethod method = new JavaMethod(runtime, jmethod);
return method.invokeDirect(getObject());
} catch (NoSuchMethodException nsme) {
throw runtime.newNameError("Java method not found", name + "()");
}
}

@JRubyMethod
public IRubyObject java_send(ThreadContext context, IRubyObject rubyName, IRubyObject argTypes) {
throw context.getRuntime().newArgumentError(2, 3);
}

@JRubyMethod
public IRubyObject java_send(ThreadContext context, IRubyObject rubyName, IRubyObject argTypes, IRubyObject arg0) {
String name = rubyName.asJavaString();
RubyArray argTypesAry = argTypes.convertToArray();
Ruby runtime = context.getRuntime();

if (argTypesAry.size() != 1) {
throw runtime.newArgumentError("arg type count (" + argTypesAry.size() + ") != arg count (1)");
}

Class argTypeClass = (Class)argTypesAry.eltInternal(0).toJava(Class.class);
Class jclass = getJavaObject().getJavaClass();

try {
Method jmethod = jclass.getMethod(name, argTypeClass);
JavaMethod method = new JavaMethod(runtime, jmethod);
return method.invokeDirect(getObject(), arg0.toJava(argTypeClass));
} catch (NoSuchMethodException nsme) {
throw runtime.newNameError("Java method not found", name + CodegenUtils.prettyParams(argTypeClass));
}
}

@JRubyMethod(required = 4, rest = true)
public IRubyObject java_send(ThreadContext context, IRubyObject[] args) {
Ruby runtime = context.getRuntime();
Arity.checkArgumentCount(runtime, args, 3, -1);

String name = args[0].asJavaString();
RubyArray argTypesAry = args[1].convertToArray();
int argsLen = args.length - 2;

if (argTypesAry.size() != argsLen) {
throw runtime.newArgumentError("arg type count (" + argTypesAry.size() + ") != arg count (" + argsLen + ")");
}

Class[] argTypesClasses = (Class[])argTypesAry.toArray(new Class[argsLen]);

Object[] argsAry = new Object[argsLen];
for (int i = 0; i < argsLen; i++) {
argsAry[i] = args[i + 2].toJava(argTypesClasses[i]);
}

Class jclass = getJavaObject().getJavaClass();

try {
Method jmethod = jclass.getMethod(name, argTypesClasses);
JavaMethod method = new JavaMethod(runtime, jmethod);
return method.invokeDirect(getObject(), argsAry);
} catch (NoSuchMethodException nsme) {
throw runtime.newNameError("Java method not found", name + CodegenUtils.prettyParams(argTypesClasses));
}
}

public Object toJava(Class type) {
getRuntime().getJavaSupport().getObjectProxyCache().put(getObject(), this);
return getObject();
Expand Down

0 comments on commit b5c0f19

Please sign in to comment.