Search code examples
javarubyjruby

How to correctly pass a Java char array as a parameter to a Ruby script via JRuby?


I'm using JRuby 9.0.5.0 in order to be able to invoke Ruby scripts from Java. I'd like to pass a char array containing a password to a Ruby script, but apparently I'm doing something wrong as my script only works if I use a normal string.

script.rb contains the following function:

def action(user, password)

From Java, I can normally invoke this function, but I only get the the expected result (i.e. no exception) if password is a String:

ScriptEngineManager m = new ScriptEngineManager();
ScriptEngine jruby = m.getEngineByName("jruby");

...

jruby.put("user", "TestUser");
jruby.put("password", "xyz!"); // I'd like to pass "xyz!" as a char array.

// Call the script. Works as expected because password is a String.
String result = (String)jruby.eval("action($user, $password)");

My first attempt was to try to pass the password like this:

char[] password = { 'x', 'y', 'z', '!' };
jruby.put("password", password);
...

but this resulted in the exception

NoMethodError: undefined method `encoding' for char[x, y, z, !]@30abf79c:# encode_utf16le at .../jruby-9.0.5.0/lib/ruby/gems/shared/gems/rubyntlm-0.6.0/lib/net/ntlm/encode_util.rb:42

I get the same error if I try to set the password explicitly in the script.rb itself like this, just for testing:

pwd = ['x', 'y', 'z', '!'].to_s
# use pwd inside the script ...

Next, I tried to force UTF-8 encoding like this:

pwd = ['x', 'y', 'z', '!'].to_s
pwd = pwd.force_encoding("UTF-8")
# use pwd inside the script ...

which resulted in a different error originating from the gem used inside the script, i.e. an authorization error. The same happens if I use "UTF-16".

Could it be that that the Ruby gem used by the script itself, i.e. the internal function call using the password, by itself only works with strings of a specific encoding? Or am I doing something else wrong? I know hardly anything about Ruby and am simply trying to glue this together.


Solution

  • The solution is to use password.to_a.pack('U*') inside the Ruby script.

    Java:

    char[] password = { 'x', 'y', 'z', '!' };
    jruby.put("password", password); // jruby is of type ScriptEngine
    

    Ruby script.rb:

    password_to_use = password.to_a.pack('U*')