embulk 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. checksums.yaml +5 -13
  2. data/.travis.yml +16 -0
  3. data/Gemfile +0 -1
  4. data/README.md +37 -19
  5. data/Rakefile +5 -37
  6. data/bin/embulk +1 -1
  7. data/build.gradle +178 -95
  8. data/embulk-core/build.gradle +1 -1
  9. data/embulk-core/src/main/java/org/embulk/command/Runner.java +11 -10
  10. data/embulk-core/src/main/java/org/embulk/config/ConfigDiff.java +26 -0
  11. data/embulk-core/src/main/java/org/embulk/config/ConfigInject.java +14 -0
  12. data/embulk-core/src/main/java/org/embulk/config/DataSourceImpl.java +2 -2
  13. data/embulk-core/src/main/java/org/embulk/config/DataSourceSerDe.java +4 -3
  14. data/embulk-core/src/main/java/org/embulk/config/TaskSerDe.java +5 -3
  15. data/embulk-core/src/main/java/org/embulk/config/TaskValidationException.java +1 -0
  16. data/embulk-core/src/main/java/org/embulk/exec/ExecutionResult.java +6 -6
  17. data/embulk-core/src/main/java/org/embulk/exec/GuessExecutor.java +19 -19
  18. data/embulk-core/src/main/java/org/embulk/exec/LocalExecutor.java +61 -36
  19. data/embulk-core/src/main/java/org/embulk/plugin/InjectedPluginSource.java +4 -0
  20. data/embulk-core/src/main/java/org/embulk/plugin/PluginManager.java +16 -1
  21. data/embulk-core/src/main/java/org/embulk/spi/Column.java +1 -1
  22. data/embulk-core/src/main/java/org/embulk/spi/{SchemaVisitor.java → ColumnVisitor.java} +1 -1
  23. data/embulk-core/src/main/java/org/embulk/spi/Exec.java +3 -3
  24. data/embulk-core/src/main/java/org/embulk/spi/ExecSession.java +2 -2
  25. data/embulk-core/src/main/java/org/embulk/spi/FileInputPlugin.java +3 -3
  26. data/embulk-core/src/main/java/org/embulk/spi/FileInputRunner.java +3 -3
  27. data/embulk-core/src/main/java/org/embulk/spi/FileOutputPlugin.java +3 -3
  28. data/embulk-core/src/main/java/org/embulk/spi/FileOutputRunner.java +3 -3
  29. data/embulk-core/src/main/java/org/embulk/spi/FilterPlugin.java +1 -1
  30. data/embulk-core/src/main/java/org/embulk/spi/GuessPlugin.java +2 -2
  31. data/embulk-core/src/main/java/org/embulk/spi/InputPlugin.java +3 -3
  32. data/embulk-core/src/main/java/org/embulk/spi/OutputPlugin.java +3 -3
  33. data/embulk-core/src/main/java/org/embulk/spi/PluginClassLoader.java +80 -0
  34. data/embulk-core/src/main/java/org/embulk/spi/Schema.java +1 -1
  35. data/embulk-core/src/main/java/org/embulk/spi/time/TimestampFormatter.java +2 -2
  36. data/embulk-core/src/main/java/org/embulk/spi/time/TimestampParser.java +2 -2
  37. data/embulk-core/src/main/java/org/embulk/spi/util/Filters.java +1 -1
  38. data/embulk-core/src/main/java/org/embulk/spi/util/LineEncoder.java +2 -2
  39. data/embulk-core/src/main/java/org/embulk/spi/util/PagePrinter.java +6 -6
  40. data/embulk-core/src/main/java/org/embulk/spi/util/Pages.java +6 -6
  41. data/embulk-core/src/test/java/org/embulk/GuiceBinder.java +1 -1
  42. data/embulk-core/src/test/java/org/embulk/plugin/MockPluginSource.java +1 -0
  43. data/embulk-core/src/test/java/org/embulk/spi/MockFormatterPlugin.java +2 -2
  44. data/embulk-core/src/test/java/org/embulk/spi/PageTestUtils.java +1 -1
  45. data/embulk-core/src/test/java/org/embulk/spi/TestFileInputRunner.java +3 -3
  46. data/embulk-core/src/test/java/org/embulk/spi/TestFileOutputRunner.java +4 -4
  47. data/embulk-docs/Makefile +178 -0
  48. data/embulk-docs/build.gradle +20 -0
  49. data/embulk-docs/make.bat +243 -0
  50. data/embulk-docs/push-gh-pages.sh +29 -0
  51. data/embulk-docs/src/conf.py +260 -0
  52. data/embulk-docs/src/index.rst +19 -0
  53. data/embulk-docs/src/release.rst +14 -0
  54. data/embulk-docs/src/release/release-0.1.0.rst +8 -0
  55. data/embulk-docs/src/release/release-0.2.0.rst +16 -0
  56. data/embulk-docs/src/release/release-0.2.1.rst +19 -0
  57. data/embulk-docs/src/release/release-0.3.0.rst +34 -0
  58. data/embulk-docs/src/release/release-0.3.1.rst +11 -0
  59. data/embulk-docs/src/release/release-0.3.2.rst +15 -0
  60. data/embulk-docs/src/release/release-0.4.0.rst +74 -0
  61. data/embulk-standards/build.gradle +0 -1
  62. data/embulk-standards/src/main/java/org/embulk/standards/CsvFormatterPlugin.java +2 -2
  63. data/embulk-standards/src/main/java/org/embulk/standards/CsvParserPlugin.java +12 -3
  64. data/embulk-standards/src/main/java/org/embulk/standards/GzipFileDecoderPlugin.java +2 -2
  65. data/embulk-standards/src/main/java/org/embulk/standards/LocalFileInputPlugin.java +49 -26
  66. data/embulk-standards/src/main/java/org/embulk/standards/LocalFileOutputPlugin.java +16 -17
  67. data/embulk-standards/src/main/java/org/embulk/standards/NullOutputPlugin.java +4 -4
  68. data/embulk-standards/src/main/java/org/embulk/standards/StandardPluginModule.java +0 -1
  69. data/embulk-standards/src/main/java/org/embulk/standards/StdoutOutputPlugin.java +5 -5
  70. data/gradle/wrapper/gradle-wrapper.jar +0 -0
  71. data/gradle/wrapper/gradle-wrapper.properties +2 -2
  72. data/lib/embulk/buffer.rb +2 -2
  73. data/lib/embulk/column.rb +6 -6
  74. data/lib/embulk/command/embulk_example.rb +1 -1
  75. data/lib/embulk/command/embulk_new_plugin.rb +87 -0
  76. data/lib/embulk/command/embulk_run.rb +84 -26
  77. data/lib/embulk/data/bundle/Gemfile +12 -20
  78. data/lib/embulk/data/bundle/embulk/{filter_example.rb → filter/example.rb} +3 -3
  79. data/lib/embulk/data/bundle/embulk/{input_example.rb → input/example.rb} +3 -3
  80. data/lib/embulk/data/bundle/embulk/{output_example.rb → output/example.rb} +3 -3
  81. data/lib/embulk/data/new/LICENSE.txt +21 -0
  82. data/lib/embulk/data/new/README.md.erb +75 -0
  83. data/lib/embulk/data/new/gitignore.erb +12 -0
  84. data/lib/embulk/data/new/java/build.gradle.erb +57 -0
  85. data/lib/embulk/data/new/java/decoder.java.erb +40 -0
  86. data/lib/embulk/data/new/java/encoder.java.erb +40 -0
  87. data/lib/embulk/data/new/java/file_input.java.erb +64 -0
  88. data/lib/embulk/data/new/java/file_output.java.erb +66 -0
  89. data/lib/embulk/data/new/java/filter.java.erb +47 -0
  90. data/lib/embulk/data/new/java/formatter.java.erb +45 -0
  91. data/lib/embulk/data/new/java/gradle/wrapper/gradle-wrapper.jar +0 -0
  92. data/lib/embulk/data/new/java/gradle/wrapper/gradle-wrapper.properties +6 -0
  93. data/lib/embulk/data/new/java/gradlew +164 -0
  94. data/lib/embulk/data/new/java/gradlew.bat +90 -0
  95. data/lib/embulk/data/new/java/input.java.erb +69 -0
  96. data/lib/embulk/data/new/java/output.java.erb +65 -0
  97. data/lib/embulk/data/new/java/parser.java.erb +51 -0
  98. data/lib/embulk/data/new/java/plugin_loader.rb.erb +3 -0
  99. data/lib/embulk/data/new/java/test.java.erb +5 -0
  100. data/lib/embulk/data/new/ruby/Gemfile +2 -0
  101. data/lib/embulk/data/new/ruby/Rakefile +1 -0
  102. data/lib/embulk/data/new/ruby/filter.rb.erb +39 -0
  103. data/lib/embulk/data/new/ruby/gemspec.erb +19 -0
  104. data/lib/embulk/data/new/ruby/input.rb.erb +47 -0
  105. data/lib/embulk/data/new/ruby/output.rb.erb +59 -0
  106. data/lib/embulk/data/package_data.rb +64 -0
  107. data/lib/embulk/data_source.rb +2 -2
  108. data/lib/embulk/decoder_plugin.rb +27 -0
  109. data/lib/embulk/encoder_plugin.rb +27 -0
  110. data/lib/embulk/error.rb +3 -0
  111. data/lib/embulk/file_input_plugin.rb +27 -0
  112. data/lib/embulk/file_output_plugin.rb +27 -0
  113. data/lib/embulk/filter_plugin.rb +28 -9
  114. data/lib/embulk/formatter_plugin.rb +105 -0
  115. data/lib/embulk/guess_csv.rb +10 -1
  116. data/lib/embulk/guess_plugin.rb +22 -27
  117. data/lib/embulk/input_plugin.rb +34 -20
  118. data/lib/embulk/java/bootstrap.rb +5 -0
  119. data/lib/embulk/java/imports.rb +7 -0
  120. data/lib/embulk/java_plugin.rb +84 -0
  121. data/lib/embulk/output_plugin.rb +35 -19
  122. data/lib/embulk/page.rb +1 -1
  123. data/lib/embulk/page_builder.rb +1 -1
  124. data/lib/embulk/parser_plugin.rb +76 -0
  125. data/lib/embulk/plugin.rb +130 -65
  126. data/lib/embulk/plugin_registry.rb +19 -8
  127. data/lib/embulk/schema.rb +4 -4
  128. data/lib/embulk/version.rb +1 -1
  129. data/settings.gradle +1 -0
  130. metadata +123 -90
  131. data/ChangeLog +0 -46
  132. data/embulk-cli/pom.xml +0 -94
  133. data/embulk-core/pom.xml +0 -148
  134. data/embulk-core/src/main/java/org/embulk/config/NextConfig.java +0 -26
  135. data/embulk-standards/pom.xml +0 -68
  136. data/embulk-standards/src/main/java/org/embulk/standards/S3FileInputPlugin.java +0 -250
  137. data/embulk-standards/src/test/java/org/embulk/standards/TestS3FileInputPlugin.java +0 -43
  138. data/pom.xml +0 -541
@@ -22,6 +22,10 @@ module Embulk
22
22
  @schema = schema
23
23
  @index = index
24
24
  @page_builder = page_builder
25
+ init
26
+ end
27
+
28
+ def init
25
29
  end
26
30
 
27
31
  def run
@@ -29,7 +33,7 @@ module Embulk
29
33
  end
30
34
 
31
35
  if Embulk.java?
32
- def self.java_object
36
+ def self.new_java
33
37
  JavaAdapter.new(self)
34
38
  end
35
39
 
@@ -41,54 +45,64 @@ module Embulk
41
45
  end
42
46
 
43
47
  def transaction(java_config, java_control)
44
- config = DataSource.from_java_object(java_config)
45
- next_config_hash = @ruby_class.transaction(config) do |task_source_hash,columns,processor_count|
46
- java_task_source = DataSource.from_ruby_hash(task_source_hash).java_object
47
- java_schema = Schema.new(columns).java_object
48
+ config = DataSource.from_java(java_config)
49
+ config_diff_hash = @ruby_class.transaction(config) do |task_source_hash,columns,processor_count|
50
+ java_task_source = DataSource.from_ruby_hash(task_source_hash).to_java
51
+ java_schema = Schema.new(columns).to_java
48
52
  java_commit_reports = java_control.run(java_task_source, java_schema, processor_count)
49
53
  java_commit_reports.map {|java_commit_report|
50
- DataSource.from_java_object(java_commit_report)
54
+ DataSource.from_java(java_commit_report)
51
55
  }
52
56
  end
53
57
  # TODO check return type of #transaction
54
- return DataSource.from_ruby_hash(next_config_hash).java_object
58
+ return DataSource.from_ruby_hash(config_diff_hash).to_java
55
59
  end
56
60
 
57
61
  def resume(java_task_source, java_schema, processor_count, java_control)
58
- task_source = DataSource.from_java_object(java_task_source)
59
- schema = Schema.from_java_object(java_schema)
60
- next_config_hash = @ruby_class.resume(task_source, schema, processor_count) do |task_source_hash,columns,processor_count|
61
- java_task_source = DataSource.from_ruby_hash(task_source_hash).java_object
62
- java_schema = Schema.new(columns).java_object
62
+ task_source = DataSource.from_java(java_task_source)
63
+ schema = Schema.from_java(java_schema)
64
+ config_diff_hash = @ruby_class.resume(task_source, schema, processor_count) do |task_source_hash,columns,processor_count|
65
+ java_task_source = DataSource.from_ruby_hash(task_source_hash).to_java
66
+ java_schema = Schema.new(columns).to_java
63
67
  java_commit_reports = java_control.run(java_task_source, java_schema, processor_count)
64
68
  java_commit_reports.map {|java_commit_report|
65
- DataSource.from_java_object(java_commit_report)
69
+ DataSource.from_java(java_commit_report)
66
70
  }
67
71
  end
68
72
  # TODO check return type of #resume
69
- return DataSource.from_ruby_hash(next_config_hash).java_object
73
+ return DataSource.from_ruby_hash(config_diff_hash).to_java
70
74
  end
71
75
 
72
76
  def cleanup(java_task_source, java_schema, processor_count, java_commit_reports)
73
- task_source = DataSource.from_java_object(java_task_source)
74
- schema = Schema.from_java_object(java_schema)
75
- commit_reports = java_commit_reports.map {|c| DataSource.from_java_object(c) }
77
+ task_source = DataSource.from_java(java_task_source)
78
+ schema = Schema.from_java(java_schema)
79
+ commit_reports = java_commit_reports.map {|c| DataSource.from_java(c) }
76
80
  @ruby_class.cleanup(task_source, schema, processor_count, commit_reports)
77
81
  return nil
78
82
  end
79
83
 
80
84
  def run(java_task_source, java_schema, processor_index, java_output)
81
- task_source = DataSource.from_java_object(java_task_source)
82
- schema = Schema.from_java_object(java_schema)
85
+ task_source = DataSource.from_java(java_task_source)
86
+ schema = Schema.from_java(java_schema)
83
87
  page_builder = PageBuilder.new(schema, java_output)
84
88
  begin
85
89
  commit_report_hash = @ruby_class.new(task_source, schema, processor_index, page_builder).run
86
- return DataSource.from_ruby_hash(commit_report_hash).java_object
90
+ return DataSource.from_ruby_hash(commit_report_hash).to_java
87
91
  ensure
88
92
  page_builder.close
89
93
  end
90
94
  end
91
95
  end
96
+
97
+ def self.from_java(java_class)
98
+ JavaPlugin.ruby_adapter_class(java_class, InputPlugin, RubyAdapter)
99
+ end
100
+
101
+ module RubyAdapter
102
+ module ClassMethods
103
+ end
104
+ # TODO
105
+ end
92
106
  end
93
107
  end
94
108
 
@@ -8,5 +8,10 @@ module Embulk
8
8
  # ModelManager
9
9
  # BufferAllocator
10
10
  end
11
+
12
+ def self.injector
13
+ # TODO use org.embulk.spi.Exec.getInjector
14
+ Injector
15
+ end
11
16
  end
12
17
  end
@@ -13,6 +13,10 @@ module Embulk::Java
13
13
  java_import 'org.embulk.spi.OutputPlugin'
14
14
  java_import 'org.embulk.spi.FilterPlugin'
15
15
  java_import 'org.embulk.spi.InputPlugin'
16
+ java_import 'org.embulk.spi.ParserPlugin'
17
+ java_import 'org.embulk.spi.FormatterPlugin'
18
+ java_import 'org.embulk.spi.EncoderPlugin'
19
+ java_import 'org.embulk.spi.DecoderPlugin'
16
20
  java_import 'org.embulk.spi.TransactionalPageOutput'
17
21
  java_import 'org.embulk.spi.PageReader'
18
22
  java_import 'org.embulk.spi.PageBuilder'
@@ -22,6 +26,9 @@ module Embulk::Java
22
26
  java_import 'org.embulk.spi.Column'
23
27
  java_import 'org.embulk.spi.type.Type'
24
28
  java_import 'org.embulk.spi.type.Types'
29
+ java_import 'org.embulk.spi.PluginClassLoader'
30
+ java_import 'org.embulk.spi.FileInputRunner'
31
+ java_import 'org.embulk.spi.FileOutputRunner'
25
32
 
26
33
  # TODO
27
34
  end
@@ -0,0 +1,84 @@
1
+ module Embulk
2
+
3
+ require 'embulk/plugin'
4
+
5
+ class JavaPlugin
6
+ def self.classloader(dir)
7
+ jars = Dir["#{dir}/**/*.jar"]
8
+ urls = jars.map {|jar| java.net.URL.new "file://#{File.expand_path(jar)}" }
9
+ classloader = Java::PluginClassLoader.new(JRuby.runtime, urls)
10
+ end
11
+
12
+ def self.register_input(name, class_fqdn, jar_dir)
13
+ java_class = classloader(jar_dir).loadClass(class_fqdn) # TODO handle class not found error
14
+ Plugin.register_java_input(name, java_class)
15
+ end
16
+
17
+ def self.register_output(name, class_fqdn, jar_dir)
18
+ java_class = classloader(jar_dir).loadClass(class_fqdn)
19
+ Plugin.register_java_output(name, java_class)
20
+ end
21
+
22
+ def self.register_filter(name, class_fqdn, jar_dir)
23
+ java_class = classloader(jar_dir).loadClass(class_fqdn)
24
+ Plugin.register_java_filter(name, java_class)
25
+ end
26
+
27
+ def self.register_parser(name, class_fqdn, jar_dir)
28
+ java_class = classloader(jar_dir).loadClass(class_fqdn)
29
+ Plugin.register_java_parser(name, java_class)
30
+ end
31
+
32
+ def self.register_formatter(name, class_fqdn, jar_dir)
33
+ java_class = classloader(jar_dir).loadClass(class_fqdn)
34
+ Plugin.register_java_formatter(name, java_class)
35
+ end
36
+
37
+ def self.register_decoder(name, class_fqdn, jar_dir)
38
+ java_class = classloader(jar_dir).loadClass(class_fqdn)
39
+ Plugin.register_java_decoder(name, java_class)
40
+ end
41
+
42
+ def self.register_encoder(name, class_fqdn, jar_dir)
43
+ java_class = classloader(jar_dir).loadClass(class_fqdn)
44
+ Plugin.register_java_encoder(name, java_class)
45
+ end
46
+
47
+ def self.register_guess(name, class_fqdn, jar_dir)
48
+ java_class = classloader(jar_dir).loadClass(class_fqdn)
49
+ Plugin.register_java_guess(name, java_class)
50
+ end
51
+
52
+ def self.ruby_adapter_class(java_class, ruby_base_class, ruby_module)
53
+ Class.new(ruby_base_class) do
54
+ const_set(:JAVA_CLASS, java_class)
55
+
56
+ include ruby_module
57
+ extend ruby_module::ClassMethods
58
+
59
+ unless method_defined?(:java_object)
60
+ def java_object
61
+ @java_object ||= self.class.new_java
62
+ end
63
+ end
64
+
65
+ unless (class<<self;self;end).method_defined?(:java_class)
66
+ def self.java_class
67
+ self::JAVA_CLASS
68
+ end
69
+ end
70
+
71
+ # TODO ruby_base_class already implements new_java. So
72
+ # this line returns always true:
73
+ #unless (class<<self;self;end).method_defined?(:new_java)
74
+ # but this line could return false unexpectedly if
75
+ # ruby_module::ClassMethods includes other modules.
76
+ unless ruby_module::ClassMethods.method_defined?(:new_java)
77
+ def self.new_java
78
+ Java.injector.getInstance(java_class)
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -22,10 +22,14 @@ module Embulk
22
22
  @task = task
23
23
  @schema = schema
24
24
  @index = index
25
+ init
25
26
  end
26
27
 
27
28
  attr_reader :task, :schema, :index
28
29
 
30
+ def init
31
+ end
32
+
29
33
  def add(page)
30
34
  raise NotImplementedError, "OutputPlugin#add(page) must be implemented"
31
35
  end
@@ -44,7 +48,7 @@ module Embulk
44
48
  end
45
49
 
46
50
  if Embulk.java?
47
- def self.java_object
51
+ def self.new_java
48
52
  JavaAdapter.new(self)
49
53
  end
50
54
 
@@ -56,44 +60,44 @@ module Embulk
56
60
  end
57
61
 
58
62
  def transaction(java_config, java_schema, processor_count, java_control)
59
- config = DataSource.from_java_object(java_config)
60
- schema = Schema.from_java_object(java_schema)
61
- next_config_hash = @ruby_class.transaction(config, schema, processor_count) do |task_source_hash|
62
- java_task_source = DataSource.from_ruby_hash(task_source_hash).java_object
63
+ config = DataSource.from_java(java_config)
64
+ schema = Schema.from_java(java_schema)
65
+ config_diff_hash = @ruby_class.transaction(config, schema, processor_count) do |task_source_hash|
66
+ java_task_source = DataSource.from_ruby_hash(task_source_hash).to_java
63
67
  java_commit_reports = java_control.run(java_task_source)
64
68
  java_commit_reports.map {|java_commit_report|
65
- DataSource.from_java_object(java_commit_report)
69
+ DataSource.from_java(java_commit_report)
66
70
  }
67
71
  end
68
72
  # TODO check return type of #transaction
69
- return DataSource.from_ruby_hash(next_config_hash).java_object
73
+ return DataSource.from_ruby_hash(config_diff_hash).to_java
70
74
  end
71
75
 
72
76
  def resume(java_task_source, java_schema, processor_count, java_control)
73
- task_source = DataSource.from_java_object(java_task_source)
74
- schema = Schema.from_java_object(java_schema)
75
- next_config_hash = @ruby_class.resume(task_source, schema, processor_count) do |task_source_hash,columns,processor_count|
76
- java_task_source = DataSource.from_ruby_hash(task_source_hash).java_object
77
+ task_source = DataSource.from_java(java_task_source)
78
+ schema = Schema.from_java(java_schema)
79
+ config_diff_hash = @ruby_class.resume(task_source, schema, processor_count) do |task_source_hash,columns,processor_count|
80
+ java_task_source = DataSource.from_ruby_hash(task_source_hash).to_java
77
81
  java_commit_reports = java_control.run(java_task_source)
78
82
  java_commit_reports.map {|java_commit_report|
79
- DataSource.from_java_object(java_commit_report)
83
+ DataSource.from_java(java_commit_report)
80
84
  }
81
85
  end
82
86
  # TODO check return type of #resume
83
- return DataSource.from_ruby_hash(next_config_hash).java_object
87
+ return DataSource.from_ruby_hash(config_diff_hash).to_java
84
88
  end
85
89
 
86
90
  def cleanup(java_task_source, java_schema, processor_count, java_commit_reports)
87
- task_source = DataSource.from_java_object(java_task_source)
88
- schema = Schema.from_java_object(java_schema)
89
- commit_reports = java_commit_reports.map {|c| DataSource.from_java_object(c) }
91
+ task_source = DataSource.from_java(java_task_source)
92
+ schema = Schema.from_java(java_schema)
93
+ commit_reports = java_commit_reports.map {|c| DataSource.from_java(c) }
90
94
  @ruby_class.cleanup(task_source, schema, processor_count, commit_reports)
91
95
  return nil
92
96
  end
93
97
 
94
98
  def open(java_task_source, java_schema, processor_index)
95
- task_source = DataSource.from_java_object(java_task_source)
96
- schema = Schema.from_java_object(java_schema)
99
+ task_source = DataSource.from_java(java_task_source)
100
+ schema = Schema.from_java(java_schema)
97
101
  ruby_object = @ruby_class.new(task_source, schema, processor_index)
98
102
  return OutputAdapter.new(ruby_object, schema)
99
103
  end
@@ -107,6 +111,7 @@ module Embulk
107
111
  end
108
112
 
109
113
  def add(java_page)
114
+ # TODO reuse page reader
110
115
  @ruby_object.add Page.new(java_page, @schema)
111
116
  end
112
117
 
@@ -124,10 +129,21 @@ module Embulk
124
129
 
125
130
  def commit
126
131
  commit_report_hash = @ruby_object.commit
127
- return DataSource.from_ruby_hash(commit_report_hash).java_object
132
+ return DataSource.from_ruby_hash(commit_report_hash).to_java
128
133
  end
129
134
  end
130
135
  end
136
+
137
+ def self.from_java(java_class)
138
+ JavaPlugin.ruby_adapter_class(java_class, OutputPlugin, RubyAdapter)
139
+ end
140
+
141
+ module RubyAdapter
142
+ module ClassMethods
143
+ # TODO transaction, resume, cleanup
144
+ end
145
+ # TODO add, finish, close, abort, commit
146
+ end
131
147
  end
132
148
  end
133
149
 
data/lib/embulk/page.rb CHANGED
@@ -15,7 +15,7 @@ module Embulk
15
15
 
16
16
  def each
17
17
  schema = @schema
18
- reader = Java::PageReader.new(schema.java_object)
18
+ reader = Java::PageReader.new(schema.to_java)
19
19
  begin
20
20
  reader.setPage(@java_page)
21
21
  while reader.nextRecord
@@ -2,7 +2,7 @@ module Embulk
2
2
 
3
3
  class PageBuilder
4
4
  def initialize(schema, java_page_output)
5
- @page_builder = Java::PageBuilder.new(Java::Injected::BufferAllocator, schema.java_object, java_page_output)
5
+ @page_builder = Java::PageBuilder.new(Java::Injected::BufferAllocator, schema.to_java, java_page_output)
6
6
  @schema = schema
7
7
  end
8
8
 
@@ -0,0 +1,76 @@
1
+ module Embulk
2
+
3
+ require 'embulk/data_source'
4
+ require 'embulk/schema'
5
+ require 'embulk/page_builder'
6
+ #require 'embulk/file_input' TODO not implemented
7
+
8
+ class ParserPlugin
9
+ def self.transaction(config, &control)
10
+ raise NotImplementedError, "ParserPlugin.transaction(config, &control) must be implemented"
11
+ end
12
+
13
+ def initialize(task, schema, page_builder)
14
+ @task = task
15
+ @schema = schema
16
+ @page_builder = page_builder
17
+ init
18
+ end
19
+
20
+ def init
21
+ end
22
+
23
+ def run(file_input)
24
+ raise NotImplementedError, "ParserPlugin#run(file_input) must be implemented"
25
+ end
26
+
27
+ if Embulk.java?
28
+ def self.new_java
29
+ JavaAdapter.new(self)
30
+ end
31
+
32
+ class JavaAdapter
33
+ include Java::ParserPlugin
34
+
35
+ def initialize(ruby_class)
36
+ @ruby_class = ruby_class
37
+ end
38
+
39
+ def transaction(java_config, java_control)
40
+ config = DataSource.from_java(java_config)
41
+ @ruby_class.transaction(config) do |task_source_hash,columns|
42
+ java_task_source = DataSource.from_ruby_hash(task_source_hash).to_java
43
+ java_schema = Schema.new(columns).to_java
44
+ java_control.run(java_task_source, java_schema)
45
+ end
46
+ nil
47
+ end
48
+
49
+ def run(java_task_source, java_schema, java_file_input, java_output)
50
+ task_source = DataSource.from_java(java_task_source)
51
+ schema = Schema.from_java(java_schema)
52
+ file_input = FileInput.from_java(java_file_input)
53
+ page_builder = PageBuilder.new(schema, java_output)
54
+ begin
55
+ @ruby_class.new(task_source, schema, page_builder).run(file_input)
56
+ nil
57
+ ensure
58
+ page_builder.close
59
+ # FileInput is closed by FileInputRunner
60
+ end
61
+ end
62
+ end
63
+
64
+ def self.from_java(java_class)
65
+ JavaPlugin.ruby_adapter_class(java_class, ParserPlugin, RubyAdapter)
66
+ end
67
+
68
+ module RubyAdapter
69
+ module ClassMethods
70
+ end
71
+ # TODO
72
+ end
73
+ end
74
+ end
75
+
76
+ end
data/lib/embulk/plugin.rb CHANGED
@@ -4,19 +4,22 @@ module Embulk
4
4
  require 'embulk/error'
5
5
  require 'embulk/plugin_registry'
6
6
  require 'embulk/input_plugin'
7
- require 'embulk/filter_plugin'
7
+ require 'embulk/file_input_plugin'
8
8
  require 'embulk/output_plugin'
9
- #require 'embulk/parser_plugin'
10
- #require 'embulk/formatter_plugin'
11
- #require 'embulk/decoder_plugin'
12
- #require 'embulk/encoder_plugin'
9
+ require 'embulk/file_output_plugin'
10
+ require 'embulk/filter_plugin'
11
+ require 'embulk/parser_plugin'
12
+ require 'embulk/formatter_plugin'
13
+ require 'embulk/decoder_plugin'
14
+ require 'embulk/encoder_plugin'
13
15
  require 'embulk/guess_plugin'
16
+ require 'embulk/java_plugin' if Embulk.java?
14
17
 
15
18
  class PluginManager
16
19
  def initialize
17
20
  @registries = {}
18
21
  %w[input output parser formatter decoder encoder line_filter filter guess].each do |category|
19
- @registries[category.to_sym] = PluginRegistry.new(category, "embulk/#{category}_")
22
+ @registries[category.to_sym] = PluginRegistry.new(category, "embulk/#{category}/")
20
23
  end
21
24
  end
22
25
 
@@ -29,101 +32,150 @@ module Embulk
29
32
  "Output plugin #{klass} must extend OutputPlugin")
30
33
  end
31
34
 
32
- def register_parser(type, klass)
33
- register_plugin(:parser, type, klass, ParserPlugin)
35
+ def register_filter(type, klass)
36
+ register_plugin(:filter, type, klass, FilterPlugin)
34
37
  end
35
38
 
36
- def register_formatter(type, klass)
37
- register_plugin(:formatter, type, klass, FormatterPlugin)
38
- end
39
+ ## TODO FileInput is not implemented yet.
40
+ #def register_parser(type, klass)
41
+ # register_plugin(:parser, type, klass, ParserPlugin)
42
+ #end
39
43
 
40
- def register_decoder(type, klass)
41
- register_plugin(:decoder, type, klass, DecoderPlugin)
42
- end
44
+ ## TODO FileOutput is not implemented yet.
45
+ #def register_formatter(type, klass)
46
+ # register_plugin(:formatter, type, klass, FormatterPlugin)
47
+ #end
43
48
 
44
- def register_encoder(type, klass)
45
- register_plugin(:encoder, type, klass, EncoderPlugin)
46
- end
49
+ ## TODO DecoderPlugin JRuby API is not written by anyone yet
50
+ #def register_decoder(type, klass)
51
+ # register_plugin(:decoder, type, klass, DecoderPlugin)
52
+ #end
47
53
 
48
- def register_filter(type, klass)
49
- register_plugin(:filter, type, klass, FilterPlugin)
50
- end
54
+ ## TODO EncoderPlugin JRuby API is not written by anyone yet
55
+ #def register_encoder(type, klass)
56
+ # register_plugin(:encoder, type, klass, EncoderPlugin)
57
+ #end
51
58
 
52
59
  def register_guess(type, klass)
53
60
  register_plugin(:guess, type, klass, GuessPlugin,
54
61
  "Guess plugin #{klass} must extend GuessPlugin, LineGuessPlugin, or TextGuessPlugin class")
55
62
  end
56
63
 
57
- def get_input(type)
58
- # TODO not implemented yet
64
+ # TODO InputPlugin::RubyAdapter is not written by anyone yet
65
+ #def get_input(type)
66
+ # lookup(:input, type)
67
+ #end
68
+
69
+ # TODO OutputPlugin::RubyAdapter is not written by anyone yet
70
+ #def get_output(type)
71
+ # lookup(:output, type)
72
+ #end
73
+
74
+ # TODO FilterPlugin::RubyAdapter is not written by anyone yet
75
+ #def get_filter(type)
76
+ # lookup(:filter, type)
77
+ #end
78
+
79
+ # TODO FilterPlugin::RubyAdapter is not written by anyone yet
80
+ #def get_parser(type)
81
+ # # TODO not implemented yet
82
+ # lookup(:parser, type)
83
+ #end
84
+
85
+ # TODO FormatterPlugin::RubyAdapter is not written by anyone yet
86
+ #def get_formatter(type)
87
+ # # TODO not implemented yet
88
+ # lookup(:formatter, type)
89
+ #end
90
+
91
+ # TODO DecoderPlugin::RubyAdapter is not written by anyone yet
92
+ #def get_decoder(type)
93
+ # # TODO not implemented yet
94
+ # lookup(:decoder, type)
95
+ #end
96
+
97
+ # TODO EncoderPlugin::RubyAdapter is not written by anyone yet
98
+ #def get_encoder(type)
99
+ # # TODO not implemented yet
100
+ # lookup(:encoder, type)
101
+ #end
102
+
103
+ def get_guess(type)
59
104
  lookup(:guess, type)
60
105
  end
61
106
 
62
- def get_output(type)
63
- # TODO not implemented yet
64
- lookup(:guess, type)
107
+ def register_java_input(type, klass)
108
+ register_java_plugin(:input, type, klass,
109
+ "org.embulk.spi.InputPlugin" => InputPlugin,
110
+ "org.embulk.spi.FileInputPlugin" => FileInputPlugin)
65
111
  end
66
112
 
67
- def get_parser(type)
68
- # TODO not implemented yet
69
- lookup(:guess, type)
113
+ def register_java_output(type, klass)
114
+ register_java_plugin(:output, type, klass,
115
+ "org.embulk.spi.OutputPlugin" => OutputPlugin,
116
+ "org.embulk.spi.FileOutputPlugin" => FileOutputPlugin)
70
117
  end
71
118
 
72
- def get_formatter(type)
73
- # TODO not implemented yet
74
- lookup(:guess, type)
119
+ def register_java_filter(type, klass)
120
+ register_java_plugin(:filter, type, klass,
121
+ "org.embulk.spi.FilterPlugin" => FilterPlugin)
75
122
  end
76
123
 
77
- def get_decoder(type)
78
- # TODO not implemented yet
79
- lookup(:guess, type)
124
+ def register_java_parser(type, klass)
125
+ register_java_plugin(:parser, type, klass,
126
+ "org.embulk.spi.ParserPlugin" => ParserPlugin)
80
127
  end
81
128
 
82
- def get_encoder(type)
83
- # TODO not implemented yet
84
- lookup(:guess, type)
129
+ def register_java_formatter(type, klass)
130
+ register_java_plugin(:formatter, type, klass,
131
+ "org.embulk.spi.FormatterPlugin" => FormatterPlugin)
85
132
  end
86
133
 
87
- def get_filter(type)
88
- # TODO not implemented yet
89
- lookup(:guess, type)
134
+ def register_java_decoder(type, klass)
135
+ register_java_plugin(:decoder, type, klass,
136
+ "org.embulk.spi.DecoderPlugin" => DecoderPlugin)
90
137
  end
91
138
 
92
- def get_guess(type)
93
- # TODO not implemented yet
94
- lookup(:guess, type)
139
+ def register_java_encoder(type, klass)
140
+ register_java_plugin(:encoder, type, klass,
141
+ "org.embulk.spi.EncoderPlugin" => EncoderPlugin)
142
+ end
143
+
144
+ def register_java_guess(type, klass)
145
+ register_java_plugin(:guess, type, klass,
146
+ "org.embulk.spi.GuessPlugin" => GuessPlugin)
95
147
  end
96
148
 
97
149
  def new_java_input(type)
98
- lookup(:input, type).java_object
150
+ lookup(:input, type).new_java
99
151
  end
100
152
 
101
153
  def new_java_output(type)
102
- lookup(:output, type).java_object
154
+ lookup(:output, type).new_java
155
+ end
156
+
157
+ def new_java_filter(type)
158
+ lookup(:filter, type).new_java
103
159
  end
104
160
 
105
161
  def new_java_parser(type)
106
- lookup(:parser, type).java_object
162
+ lookup(:parser, type).new_java
107
163
  end
108
164
 
109
165
  def new_java_formatter(type)
110
- lookup(:formatter, type).java_object
166
+ lookup(:formatter, type).new_java
111
167
  end
112
168
 
113
169
  def new_java_decoder(type)
114
- lookup(:decoder, type).java_object
170
+ lookup(:decoder, type).new_java
115
171
  end
116
172
 
117
173
  def new_java_encoder(type)
118
- lookup(:encoder, type).java_object
119
- end
120
-
121
- def new_java_filter(type)
122
- lookup(:filter, type).java_object
174
+ lookup(:encoder, type).new_java
123
175
  end
124
176
 
125
177
  def new_java_guess(type)
126
- lookup(:guess, type).java_object
178
+ lookup(:guess, type).new_java
127
179
  end
128
180
 
129
181
  private
@@ -136,13 +188,26 @@ module Embulk
136
188
  @registries[category].lookup(type)
137
189
  end
138
190
 
139
- def register_plugin(category, type, klass, iface, message=nil)
140
- unless klass < iface
141
- message ||= "Plugin #{klass} must implement #{iface}"
191
+ def register_plugin(category, type, klass, base_class, message=nil)
192
+ unless klass < base_class
193
+ message ||= "Plugin #{klass} must inherit #{base_class}"
142
194
  raise message
143
195
  end
144
196
  @registries[category].register(type, klass)
145
197
  end
198
+
199
+ def register_java_plugin(category, type, klass, iface_map, message=nil)
200
+ found = iface_map.find do |iface_name,ruby_base_class|
201
+ iface = JRuby.runtime.getJRubyClassLoader.load_class(iface_name)
202
+ iface.isAssignableFrom(klass)
203
+ end
204
+ unless found
205
+ message ||= "Java plugin #{klass} must implement #{iface_map.keys.join(' or ')}"
206
+ raise message
207
+ end
208
+ adapted = found.last.from_java(klass)
209
+ @registries[category].register(type, adapted)
210
+ end
146
211
  end
147
212
 
148
213
  module Plugin
@@ -152,14 +217,14 @@ module Embulk
152
217
  extend Forwardable
153
218
 
154
219
  def_delegators 'INSTANCE',
155
- :register_input, :get_input, :new_java_input,
156
- :register_output, :get_output, :new_java_output,
157
- :register_parser, :get_parser, :new_java_parser,
158
- :register_formatter, :get_formatter, :new_java_formatter,
159
- :register_decoder, :get_decoder, :new_java_decoder,
160
- :register_encoder, :get_encoder, :new_java_encoder,
161
- :register_filter, :get_filter, :new_java_filter,
162
- :register_guess, :get_guess, :new_java_guess
220
+ :register_input, :get_input, :register_java_input, :new_java_input,
221
+ :register_output, :get_output, :register_java_output, :new_java_output,
222
+ :register_filter, :get_filter, :register_java_filter, :new_java_filter,
223
+ :register_parser, :get_parser, :register_java_parser, :new_java_parser,
224
+ :register_formatter, :get_formatter, :register_java_formatter, :new_java_formatter,
225
+ :register_decoder, :get_decoder, :register_java_decoder, :new_java_decoder,
226
+ :register_encoder, :get_encoder, :register_java_encoder, :new_java_encoder,
227
+ :register_guess, :get_guess, :register_java_guess, :new_java_guess
163
228
  end
164
229
  end
165
230
  end