1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
module Inline
  require 'java'
  
  class Java
    $CLASSPATH << Inline.directory
    
    JFile = java.io.File
    import javax.tools.ToolProvider
    import javax.tools.SimpleJavaFileObject
    import javax.tools.StandardLocation

    def initialize(mod)
      @context = mod
      @src = ""
      @imports = []
      @sigs = []
    end

    def import(cls)
      @imports << cls
    end
    
    def load_cache
      false
    end

    def java(src)
      @src << src << "\n"
      signature = @src.match(/public static\W+(\w+)\W+([a-zA-Z0-9_]+)\((.*)\)/)
      raise "Could not parse method signature" unless signature
      @sigs << [signature[1], signature[2], signature[3]]
    end

    def build
      compiler = ToolProvider.system_java_compiler
      file_mgr = compiler.get_standard_file_manager(nil, nil, nil)
      file_mgr.set_location(StandardLocation::CLASS_OUTPUT, [JFile.new(Inline.directory)])
      
      @name = "Java#{@src.hash.abs}"
      
      imports = "import " + @imports.join(";\nimport ") + ";" if @imports.size > 0
      full_src = "
        #{imports}
        public class #{@name} {
        #{@src}
        }
      "
      
      filename = "#{Inline.directory}/#{@name}.java"
      File.open(filename, "w") {|file| file.write(full_src)}
      file_objs = file_mgr.get_java_file_objects_from_strings([filename])
      
      compiler.get_task(nil, file_mgr, nil, nil, nil, file_objs).call
      file_mgr.close
    end

    def load
      @sigs.each do |sig|
        @context.module_eval "const_set :#{@name}, ::Java.const_get(:#{@name}); def #{sig[1]}(*args); #{@name}.#{sig[1]}(*args); end"
      end
    end
  end
end