loading JRuby classes from Java by Class.forName
I have following class in Java code:
public class CHRTreeCreator extends IndexCreator { ... }
Instead CHRTreeCreator
I want to use diffrent implementation which also extends IndexCreator
, but I want to code it in JRuby. The problem is, specific implementation of IndexCreator
is chosen based on xml config file:
<creator>dwe.index.tree.chr.CHRTreeCreator</creator>
the code looks like this:
// className is fetched from XML
Class creatorClass = Class.forName(className);
Constructor constructor = creatorClass.getConstructor(new Class[] { });
creator = (IndexCreator) constructor.newInstance(new Object[] { });
The question is, is it possible to implement it in Ruby, like this:
class MyIndexCreator < IndexCreator
end
and someho开发者_运维问答w put MyIndexCreator
class name into XML config file. How does module - packages mapping work in that case?
If it's not possible to load Ruby classes by Java's Class.forName, how should I solve that issue?
Currently JRuby subclasses are not accessible via Java in this way, although it is planned in some capacity for future implementations (JRuby 1.5 perhaps).
One option (depending on the API of your class) is to create a delegate:
public class RubyIndexCreator extends IndexCreator {
private IndexCreator rubyCreator;
public RubyIndexCreator() {
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("ruby");
FileReader r = new FileReader("ruby_index_creator.rb");
try {
rubyCreator = engine.eval(r);
}
finally {
r.close();
}
}
public Object create(String someArg) {
return rubyCreator.create(someArg);
}
}
I've glossed over some opportunities for caching, and also just sketched out managing the file reader, but hopefully you get the picture.
In this particular example, ruby_index_creator.rb
would implement your index creator class, and then return an instance of it - obviously from here you can reference other ruby files, and organize as appropriate:
class MyIndexer < IndexCreator
[...]
end
MyIndexer.new
That's about it!
As an alternative, perhaps you could take advantage of Ruby's Open Classes and modify the behaviour of CHRTreeCreator directly (as opposed to sub-classing).
How about using ruby eval:
C:\>jirb
irb(main):001:0> require 'java'
=> false
irb(main):002:0> class MyDate < Java::JavaUtil::Date
irb(main):003:1> def my_method;puts "hi there";end
irb(main):004:1> end
=> nil
irb(main):005:0>
irb(main):006:0* c = "MyDate"
=> "MyDate"
irb(main):007:0> obj = eval("#{c}.new")
=> #<MyDate:0xd2efa1>
irb(main):008:0> obj.my_method
hi there
=> nil
irb(main):009:0>
精彩评论