I am trying to embed and evaluate ruby code from a Java application. Instead of putting jruby-complete.jar in my classpath, I need to be able to use the jruby environment installed with rvm. I can execute the core kernel code, but I am having problems requiring standard libraries (fileutils, tmpdir, etc.).
I created a test file below that uses JRuby installed via RVM, everyone should be able to compile + run it if you have a local installation of rvm + jruby installed (change JRUBY_VERSION to the installed version). I understand that the jruby.jar I am referring to does not match jruby-complete.jar, but I hope there is a way to load the standard libraries without loading the external jar.
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.logging.Logger;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
public class Test {
private final static Logger LOG = Logger.getAnonymousLogger();
private final static String JRUBY_VERSION = "jruby-1.6.7";
public static void main(String[] args) throws Throwable {
final String rvmPath = System.getenv("HOME") + "/.rvm/rubies/";
addFileToClasspath(rvmPath + JRUBY_VERSION + "/lib/jruby.jar");
final ScriptEngine rubyEngine = new ScriptEngineManager().getEngineByName("jruby");
rubyEval(rubyEngine, "puts 'hello world!'");
rubyEval(rubyEngine, "require 'tempfile'");
rubyEval(rubyEngine, "require 'fileutils'");
}
private static void rubyEval(ScriptEngine rubyEngine, final String code) {
try {
rubyEngine.eval(code);
} catch (final Throwable e) { LOG.throwing(Test.class.getName(), "rubyEval", e); };
}
public static void addFileToClasspath(final String path) throws Throwable {
final File file = new File(path);
final URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
final Class<?> sysclass = URLClassLoader.class;
final Method method = sysclass.getDeclaredMethod("addURL", new Class<?>[] {URL.class});
method.setAccessible(true);
method.invoke(sysloader, new Object[] {file.toURI().toURL()});
}
}