diff --git a/core/src/main/java/org/jruby/ir/instructions/RuntimeHelperCall.java b/core/src/main/java/org/jruby/ir/instructions/RuntimeHelperCall.java index dd692a15820..abb35ebd4f3 100644 --- a/core/src/main/java/org/jruby/ir/instructions/RuntimeHelperCall.java +++ b/core/src/main/java/org/jruby/ir/instructions/RuntimeHelperCall.java @@ -29,8 +29,10 @@ public enum Methods { IS_DEFINED_CLASS_VAR, IS_DEFINED_SUPER, IS_DEFINED_METHOD, IS_DEFINED_CALL, IS_DEFINED_CONSTANT_OR_METHOD, MERGE_KWARGS, IS_HASH_EMPTY, HASH_CHECK, ARRAY_LENGTH; - public static Methods fromOrdinal(int value) { - return value < 0 || value >= values().length ? null : values()[value]; + private static final Methods[] VALUES = values(); + + static Methods fromOrdinal(int value) { + return value < 0 || value >= VALUES.length ? null : VALUES[value]; } } diff --git a/core/src/main/java/org/jruby/javasupport/JavaEmbedUtils.java b/core/src/main/java/org/jruby/javasupport/JavaEmbedUtils.java index 44a322753f7..64c7e1ff432 100644 --- a/core/src/main/java/org/jruby/javasupport/JavaEmbedUtils.java +++ b/core/src/main/java/org/jruby/javasupport/JavaEmbedUtils.java @@ -43,20 +43,24 @@ import org.jruby.runtime.Block; import org.jruby.runtime.Helpers; import org.jruby.runtime.builtin.IRubyObject; -import org.jruby.util.UriLikePathHelper; /** - * Utility functions to help embedders out. These function consolidate logic that is - * used between BSF and JSR 223. People who are embedding JRuby 'raw' should use these - * as well. If at a later date, we discover a flaw or change how we do things, this - * utility class should provide some insulation. + * Utility functions to help embedders out. + * These function consolidate logic that is used between BSF and JSR 223. + * People who are embedding JRuby 'raw' should use these as well. + * If at a later date, we discover a flaw or change how we do things, this utility class should provide some insulation. * + *
  * Example:
- * Ruby runtime = JavaEmbedUtils.initialize(new ArrayList());
- * RubyRuntimeAdapter evaler = JavaEmbedUtils.newRuntimeAdapter();
- * IRubyObject rubyObject = evaler.parse(runtime, expr.toString(), file, line).run());
- * SomeClassOrInterface javaObject = (SomeClassOrInterface) JavaEmbedUtils.rubyToJava(rubyObject);
- * runtime.terminate();
+ *
+ *   Ruby runtime = JavaEmbedUtils.initialize(List.of("a/custom/load/path"));
+ *
+ *   RubyRuntimeAdapter evaler = JavaEmbedUtils.newRuntimeAdapter();
+ *   IRubyObject rubyObject = evaler.parse(runtime, expr.toString(), file, line).run());
+ *   SomeClassOrInterface javaObject = JavaEmbedUtils.rubyToJava(rubyObject, SomeClassOrInterface.class);
+ *
+ *   runtime.terminate();
+ * 
*/ public class JavaEmbedUtils { /** @@ -223,7 +227,7 @@ public static void terminate(Ruby runtime) { * @return the result of the invocation. */ @SuppressWarnings("deprecation") - public static Object invokeMethod(Ruby runtime, Object receiver, String method, Object[] args, Class returnType) { + public static T invokeMethod(Ruby runtime, Object receiver, String method, Object[] args, Class returnType) { IRubyObject rubyReceiver = receiver != null ? JavaUtil.convertJavaToRuby(runtime, receiver) : runtime.getTopSelf(); IRubyObject[] rubyArgs = JavaUtil.convertJavaArrayToRuby(runtime, args); @@ -243,7 +247,12 @@ public static Object invokeMethod(Ruby runtime, Object receiver, String method, /** * Convert a Ruby object to a Java object. */ - public static Object rubyToJava(Ruby runtime, IRubyObject value, Class type) { + public static T rubyToJava(IRubyObject value, Class type) { + return value.toJava(type); + } + + // @Deprecated + public static T rubyToJava(Ruby runtime, IRubyObject value, Class type) { return value.toJava(type); } @@ -252,8 +261,8 @@ public static Object rubyToJava(Ruby runtime, IRubyObject value, Class type) { * @param value to be converted * @return the converted object */ - public static Object rubyToJava(IRubyObject value) { - return value.toJava(Object.class); + public static T rubyToJava(IRubyObject value) { + return (T) value.toJava(Object.class); } /** @@ -261,8 +270,6 @@ public static Object rubyToJava(IRubyObject value) { */ @SuppressWarnings("deprecation") public static IRubyObject javaToRuby(Ruby runtime, Object value) { - if (value instanceof IRubyObject) return (IRubyObject) value; - IRubyObject result = JavaUtil.convertJavaToUsableRubyObject(runtime, value); return result instanceof JavaObject ? Java.wrap(runtime, result) : result; diff --git a/core/src/test/java/org/jruby/javasupport/JavaEmbedUtilsTest.java b/core/src/test/java/org/jruby/javasupport/JavaEmbedUtilsTest.java index a5694771cc8..8773b940d32 100644 --- a/core/src/test/java/org/jruby/javasupport/JavaEmbedUtilsTest.java +++ b/core/src/test/java/org/jruby/javasupport/JavaEmbedUtilsTest.java @@ -3,14 +3,20 @@ import java.io.File; import java.net.URL; import java.net.URLClassLoader; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.List; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import org.jruby.java.proxies.ConcreteJavaProxy; +import org.jruby.java.proxies.JavaProxy; +import org.jruby.runtime.builtin.IRubyObject; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; @@ -65,4 +71,90 @@ public void testAddClassloaderToLoadPathOnNoneTCCL() throws Exception { String result = runtime.evalScriptlet("require 'test_me';$result").toString(); assertEquals(result, "uri:" + url); } + + @Test + public void testAPIUsageTheNonGenericWay() { // before generic signatures were introduced (JRuby <= 9.4.0) + final Ruby runtime = Ruby.newInstance(); + IRubyObject str = runtime.evalScriptlet("'foo'"); + Object javaStr = JavaEmbedUtils.rubyToJava(runtime, str, String.class); + assertEquals("foo", javaStr); + + str = runtime.evalScriptlet("'bar' * 3"); + javaStr = JavaEmbedUtils.rubyToJava(runtime, str, Object.class); + assertEquals("barbarbar", javaStr); + + Object val = JavaEmbedUtils.rubyToJava(runtime.newEmptyArray()); + assertEquals("org.jruby.RubyArray", val.getClass().getName()); + } + + @Test + public void testJavaToRubyPrimitive() { + final Ruby runtime = Ruby.newInstance(); + + IRubyObject v; + v = JavaEmbedUtils.javaToRuby(runtime, -100L); + assertEquals(runtime.newFixnum(-100), v); + + v = JavaEmbedUtils.javaToRuby(runtime, 200); + assertEquals(runtime.newFixnum(200), v); + + v = JavaEmbedUtils.javaToRuby(runtime, (short) 200); + assertEquals(runtime.newFixnum(200), v); + + v = JavaEmbedUtils.javaToRuby(runtime, (byte) 100); + assertEquals(runtime.newFixnum(100), v); + + v = JavaEmbedUtils.javaToRuby(runtime, 10.0f); + assertEquals(runtime.newFloat(10.0), v); + + v = JavaEmbedUtils.javaToRuby(runtime, 10.0d); + assertEquals(runtime.newFloat(10.0), v); + + v = JavaEmbedUtils.javaToRuby(runtime, true); + assertSame(runtime.getTrue(), v); + + v = JavaEmbedUtils.javaToRuby(runtime, false); + assertSame(runtime.getFalse(), v); + } + + @Test + public void testJavaToRuby() { + final Ruby runtime = Ruby.newInstance(); + + IRubyObject v; + v = JavaEmbedUtils.javaToRuby(runtime, ""); + assertEquals(runtime.newString(), v); + + v = JavaEmbedUtils.javaToRuby(runtime, Long.valueOf(42L)); + assertEquals(runtime.newFixnum(42), v); + + v = JavaEmbedUtils.javaToRuby(runtime, Boolean.TRUE); + assertSame(runtime.getTrue(), v); + + v = JavaEmbedUtils.javaToRuby(runtime, new StringBuilder()); + assertEquals(ConcreteJavaProxy.class, v.getClass()); // no more JavaObject wrapping! + } + + @Test + public void testRubyToJava() { + final Ruby runtime = Ruby.newInstance(); + + CharSequence sym = JavaEmbedUtils.rubyToJava(runtime.newSymbol("foo"), CharSequence.class); + assertEquals("foo", sym); + } + + @Test + public void testJavaToRubyAndRubyToJava() { + final Ruby runtime = Ruby.newInstance(); + + IRubyObject v = JavaEmbedUtils.javaToRuby(runtime, new ArrayList<>(Arrays.asList("1", '2', 3))); + assertTrue(v instanceof JavaProxy); + List val = JavaEmbedUtils.rubyToJava(v); + assertEquals(3, val.size()); + + assertEquals(java.util.ArrayList.class, val.getClass()); + + Collection coll = JavaEmbedUtils.rubyToJava(v, Collection.class); + assertSame(val, coll); + } } \ No newline at end of file