embulk 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +8 -8
  2. data/ChangeLog +12 -0
  3. data/README.md +38 -13
  4. data/build.gradle +6 -1
  5. data/embulk-cli/pom.xml +1 -1
  6. data/embulk-core/pom.xml +1 -1
  7. data/embulk-core/src/main/java/org/embulk/command/Runner.java +87 -8
  8. data/embulk-core/src/main/java/org/embulk/config/ConfigSource.java +1 -1
  9. data/embulk-core/src/main/java/org/embulk/config/DataSourceImpl.java +16 -3
  10. data/embulk-core/src/main/java/org/embulk/config/TaskSource.java +1 -1
  11. data/embulk-core/src/main/java/org/embulk/exec/ExecutionInterruptedException.java +10 -0
  12. data/embulk-core/src/main/java/org/embulk/exec/ExecutionResult.java +26 -0
  13. data/embulk-core/src/main/java/org/embulk/exec/GuessExecutor.java +37 -1
  14. data/embulk-core/src/main/java/org/embulk/exec/LocalExecutor.java +461 -110
  15. data/embulk-core/src/main/java/org/embulk/exec/PartialExecutionException.java +18 -0
  16. data/embulk-core/src/main/java/org/embulk/exec/ResumeState.java +82 -0
  17. data/embulk-core/src/main/java/org/embulk/jruby/JRubyPluginSource.java +3 -3
  18. data/embulk-core/src/main/java/org/embulk/spi/ExecSession.java +35 -4
  19. data/embulk-core/src/main/java/org/embulk/spi/FileInputPlugin.java +14 -3
  20. data/embulk-core/src/main/java/org/embulk/spi/FileInputRunner.java +55 -24
  21. data/embulk-core/src/main/java/org/embulk/spi/FileOutputPlugin.java +8 -0
  22. data/embulk-core/src/main/java/org/embulk/spi/FileOutputRunner.java +57 -24
  23. data/embulk-core/src/main/java/org/embulk/spi/FilterPlugin.java +21 -0
  24. data/embulk-core/src/main/java/org/embulk/spi/InputPlugin.java +14 -3
  25. data/embulk-core/src/main/java/org/embulk/spi/OutputPlugin.java +8 -0
  26. data/embulk-core/src/main/java/org/embulk/spi/util/Filters.java +87 -0
  27. data/embulk-core/src/test/java/org/embulk/EmbulkTestRuntime.java +4 -2
  28. data/embulk-core/src/test/java/org/embulk/spi/TestFileInputRunner.java +16 -0
  29. data/embulk-core/src/test/java/org/embulk/spi/TestFileOutputRunner.java +15 -0
  30. data/embulk-standards/pom.xml +1 -1
  31. data/embulk-standards/src/main/java/org/embulk/standards/LocalFileInputPlugin.java +16 -2
  32. data/embulk-standards/src/main/java/org/embulk/standards/LocalFileOutputPlugin.java +14 -1
  33. data/embulk-standards/src/main/java/org/embulk/standards/NullOutputPlugin.java +14 -1
  34. data/embulk-standards/src/main/java/org/embulk/standards/S3FileInputPlugin.java +15 -3
  35. data/embulk-standards/src/main/java/org/embulk/standards/StdoutOutputPlugin.java +15 -1
  36. data/lib/embulk/command/embulk_run.rb +16 -1
  37. data/lib/embulk/data/bundle/embulk/filter_example.rb +42 -0
  38. data/lib/embulk/data/bundle/embulk/input_example.rb +43 -33
  39. data/lib/embulk/data/bundle/embulk/output_example.rb +43 -36
  40. data/lib/embulk/filter_plugin.rb +86 -0
  41. data/lib/embulk/input_plugin.rb +37 -2
  42. data/lib/embulk/java/imports.rb +1 -0
  43. data/lib/embulk/output_plugin.rb +30 -0
  44. data/lib/embulk/plugin.rb +32 -19
  45. data/lib/embulk/schema.rb +16 -9
  46. data/lib/embulk/version.rb +1 -1
  47. data/pom.xml +1 -1
  48. metadata +13 -7
  49. data/embulk-core/src/main/java/org/embulk/exec/ExecuteInterruptedException.java +0 -10
  50. data/embulk-core/src/main/java/org/embulk/exec/ExecuteResult.java +0 -19
@@ -1,51 +1,58 @@
1
1
  module Embulk
2
+ module Plugin
2
3
 
3
- class OutputExample < OutputPlugin
4
- # output plugin file name must be: embulk/output_<name>.rb
5
- Plugin.register_output('example', self)
4
+ class OutputExample < OutputPlugin
5
+ # output plugin file name must be: embulk/output_<name>.rb
6
+ Plugin.register_output('example', self)
6
7
 
7
- def self.transaction(config, schema, processor_count, &control)
8
- task = {
9
- 'message' => config.param('message', :string, default: "record")
10
- }
8
+ def self.transaction(config, schema, count, &control)
9
+ task = {
10
+ 'message' => config.param('message', :string, default: "record")
11
+ }
11
12
 
12
- puts "Example output started."
13
- commit_reports = yield(task)
14
- puts "Example output finished. Commit reports = #{commit_reports.to_json}"
13
+ resume(task, schema, count, &control)
14
+ end
15
15
 
16
- return {}
17
- end
16
+ def self.resume(task, schema, count, &control)
17
+ puts "Example output started."
18
+ commit_reports = yield(task)
19
+ puts "Example output finished. Commit reports = #{commit_reports.to_json}"
18
20
 
19
- def initialize(task, schema, index)
20
- puts "Example output thread #{index}..."
21
- super
22
- @message = task.param('message', :string)
23
- @records = 0
24
- end
21
+ next_config_diff = {}
22
+ return next_config_diff
23
+ end
25
24
 
26
- def close
27
- end
25
+ def initialize(task, schema, index)
26
+ puts "Example output thread #{index}..."
27
+ super
28
+ @message = task.param('message', :string)
29
+ @records = 0
30
+ end
28
31
 
29
- def add(page)
30
- page.each do |record|
31
- hash = Hash[schema.names.zip(record)]
32
- puts "#{@message}: #{hash.to_json}"
33
- @records += 1
32
+ def close
34
33
  end
35
- end
36
34
 
37
- def finish
38
- end
35
+ def add(page)
36
+ page.each do |record|
37
+ hash = Hash[schema.names.zip(record)]
38
+ STDOUT.write "#{@message}: #{hash.to_json}\n"
39
+ @records += 1
40
+ end
41
+ end
39
42
 
40
- def abort
41
- end
43
+ def finish
44
+ end
45
+
46
+ def abort
47
+ end
42
48
 
43
- def commit
44
- commit_report = {
45
- "records" => @records
46
- }
47
- return commit_report
49
+ def commit
50
+ commit_report = {
51
+ "records" => @records
52
+ }
53
+ return commit_report
54
+ end
48
55
  end
49
- end
50
56
 
57
+ end
51
58
  end
@@ -0,0 +1,86 @@
1
+ module Embulk
2
+
3
+ class FilterPlugin
4
+ def self.transaction(config, in_schema, &control)
5
+ yield(config)
6
+ return {}
7
+ end
8
+
9
+ def initialize(task, in_schema, out_schema, page_builder)
10
+ @task = task
11
+ @in_schema = in_schema
12
+ @out_schema = out_schema
13
+ @page_builder = page_builder
14
+ end
15
+
16
+ attr_reader :task, :in_schema, :out_schema, :page_builder
17
+
18
+ def add(page)
19
+ raise NotImplementedError, "FilterPlugin#add(page) must be implemented"
20
+ end
21
+
22
+ def finish
23
+ end
24
+
25
+ def close
26
+ end
27
+
28
+ if Embulk.java?
29
+ def self.java_object
30
+ JavaAdapter.new(self)
31
+ end
32
+
33
+ class JavaAdapter
34
+ include Java::FilterPlugin
35
+
36
+ def initialize(ruby_class)
37
+ @ruby_class = ruby_class
38
+ end
39
+
40
+ def transaction(java_config, java_in_schema, java_control)
41
+ config = DataSource.from_java_object(java_config)
42
+ in_schema = Schema.from_java_object(java_in_schema)
43
+ @ruby_class.transaction(config, in_schema) do |task_source_hash, out_columns|
44
+ java_task_source = DataSource.from_ruby_hash(task_source_hash).java_object
45
+ java_out_schemas = Schema.new(out_columns).java_object
46
+ java_control.run(java_task_source, java_out_schemas)
47
+ end
48
+ nil
49
+ end
50
+
51
+ def open(java_task_source, java_in_schema, java_out_schema, java_output)
52
+ task_source = DataSource.from_java_object(java_task_source)
53
+ in_schema = Schema.from_java_object(java_in_schema)
54
+ out_schema = Schema.from_java_object(java_out_schema)
55
+ page_builder = PageBuilder.new(out_schema, java_output)
56
+ ruby_object = @ruby_class.new(task_source, in_schema, out_schema, page_builder)
57
+ return OutputAdapter.new(ruby_object, in_schema, page_builder)
58
+ end
59
+
60
+ class OutputAdapter
61
+ include Java::TransactionalPageOutput
62
+
63
+ def initialize(ruby_object, in_schema, page_builder)
64
+ @ruby_object = ruby_object
65
+ @in_schema = in_schema
66
+ @page_builder = page_builder
67
+ end
68
+
69
+ def add(java_page)
70
+ @ruby_object.add Page.new(java_page, @in_schema)
71
+ end
72
+
73
+ def finish
74
+ @ruby_object.finish
75
+ end
76
+
77
+ def close
78
+ @ruby_object.close
79
+ ensure
80
+ @page_builder.close
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -9,6 +9,14 @@ module Embulk
9
9
  raise NotImplementedError, "InputPlugin.transaction(config, &control) must be implemented"
10
10
  end
11
11
 
12
+ def self.resume(task, columns, count, &control)
13
+ raise NotImplementedError, "#{self}.resume(task, columns, count, &control) is not implemented. This plugin is not resumable"
14
+ end
15
+
16
+ def self.cleanup(task, schema, count, commit_reports)
17
+ # do nothing by default
18
+ end
19
+
12
20
  def initialize(task, schema, index, page_builder)
13
21
  @task = task
14
22
  @schema = schema
@@ -46,12 +54,39 @@ module Embulk
46
54
  return DataSource.from_ruby_hash(next_config_hash).java_object
47
55
  end
48
56
 
57
+ 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
63
+ java_commit_reports = java_control.run(java_task_source, java_schema, processor_count)
64
+ java_commit_reports.map {|java_commit_report|
65
+ DataSource.from_java_object(java_commit_report)
66
+ }
67
+ end
68
+ # TODO check return type of #resume
69
+ return DataSource.from_ruby_hash(next_config_hash).java_object
70
+ end
71
+
72
+ 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) }
76
+ @ruby_class.cleanup(task_source, schema, processor_count, commit_reports)
77
+ return nil
78
+ end
79
+
49
80
  def run(java_task_source, java_schema, processor_index, java_output)
50
81
  task_source = DataSource.from_java_object(java_task_source)
51
82
  schema = Schema.from_java_object(java_schema)
52
83
  page_builder = PageBuilder.new(schema, java_output)
53
- commit_report_hash = @ruby_class.new(task_source, schema, processor_index, page_builder).run
54
- return DataSource.from_ruby_hash(commit_report_hash).java_object
84
+ begin
85
+ 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
87
+ ensure
88
+ page_builder.close
89
+ end
55
90
  end
56
91
  end
57
92
  end
@@ -11,6 +11,7 @@ module Embulk::Java
11
11
  java_import 'org.embulk.spi.time.Timestamp'
12
12
  java_import 'org.embulk.spi.GuessPlugin'
13
13
  java_import 'org.embulk.spi.OutputPlugin'
14
+ java_import 'org.embulk.spi.FilterPlugin'
14
15
  java_import 'org.embulk.spi.InputPlugin'
15
16
  java_import 'org.embulk.spi.TransactionalPageOutput'
16
17
  java_import 'org.embulk.spi.PageReader'
@@ -10,6 +10,14 @@ module Embulk
10
10
  return {}
11
11
  end
12
12
 
13
+ def self.resume(task, schema, count, &control)
14
+ raise NotImplementedError, "#{self}.resume(task, schema, count, &control) is not implemented. This plugin is not resumable"
15
+ end
16
+
17
+ def self.cleanup(task, schema, count, commit_reports)
18
+ # do nothing by default
19
+ end
20
+
13
21
  def initialize(task, schema, index)
14
22
  @task = task
15
23
  @schema = schema
@@ -61,6 +69,28 @@ module Embulk
61
69
  return DataSource.from_ruby_hash(next_config_hash).java_object
62
70
  end
63
71
 
72
+ 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
+ java_commit_reports = java_control.run(java_task_source)
78
+ java_commit_reports.map {|java_commit_report|
79
+ DataSource.from_java_object(java_commit_report)
80
+ }
81
+ end
82
+ # TODO check return type of #resume
83
+ return DataSource.from_ruby_hash(next_config_hash).java_object
84
+ end
85
+
86
+ 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) }
90
+ @ruby_class.cleanup(task_source, schema, processor_count, commit_reports)
91
+ return nil
92
+ end
93
+
64
94
  def open(java_task_source, java_schema, processor_index)
65
95
  task_source = DataSource.from_java_object(java_task_source)
66
96
  schema = Schema.from_java_object(java_schema)
@@ -4,6 +4,7 @@ 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
8
  require 'embulk/output_plugin'
8
9
  #require 'embulk/parser_plugin'
9
10
  #require 'embulk/formatter_plugin'
@@ -14,7 +15,7 @@ module Embulk
14
15
  class PluginManager
15
16
  def initialize
16
17
  @registries = {}
17
- %w[input output parser formatter decoder encoder line_filter guess].each do |category|
18
+ %w[input output parser formatter decoder encoder line_filter filter guess].each do |category|
18
19
  @registries[category.to_sym] = PluginRegistry.new(category, "embulk/#{category}_")
19
20
  end
20
21
  end
@@ -44,6 +45,10 @@ module Embulk
44
45
  register_plugin(:encoder, type, klass, EncoderPlugin)
45
46
  end
46
47
 
48
+ def register_filter(type, klass)
49
+ register_plugin(:filter, type, klass, FilterPlugin)
50
+ end
51
+
47
52
  def register_guess(type, klass)
48
53
  register_plugin(:guess, type, klass, GuessPlugin,
49
54
  "Guess plugin #{klass} must extend GuessPlugin, LineGuessPlugin, or TextGuessPlugin class")
@@ -79,6 +84,11 @@ module Embulk
79
84
  lookup(:guess, type)
80
85
  end
81
86
 
87
+ def get_filter(type)
88
+ # TODO not implemented yet
89
+ lookup(:guess, type)
90
+ end
91
+
82
92
  def get_guess(type)
83
93
  # TODO not implemented yet
84
94
  lookup(:guess, type)
@@ -108,6 +118,10 @@ module Embulk
108
118
  lookup(:encoder, type).java_object
109
119
  end
110
120
 
121
+ def new_java_filter(type)
122
+ lookup(:filter, type).java_object
123
+ end
124
+
111
125
  def new_java_guess(type)
112
126
  lookup(:guess, type).java_object
113
127
  end
@@ -131,22 +145,21 @@ module Embulk
131
145
  end
132
146
  end
133
147
 
134
- Plugin = PluginManager.new
135
-
136
- #module Plugin
137
- # class <<self
138
- # INSTANCE = PluginManager.new
139
- #
140
- # extend Forwardable
141
- #
142
- # def_delegators 'INSTANCE',
143
- # :register_input, :new_input, :new_java_input,
144
- # :register_output, :new_output, :new_java_output,
145
- # :register_parser, :new_parser, :new_java_parser,
146
- # :register_formatter, :new_formatter, :new_java_formatter,
147
- # :register_decoder, :new_decoder, :new_java_decoder,
148
- # :register_encoder, :new_encoder, :new_java_encoder,
149
- # :register_guess, :new_guess, :new_java_guess
150
- # end
151
- #end
148
+ module Plugin
149
+ class <<self
150
+ INSTANCE = PluginManager.new
151
+
152
+ extend Forwardable
153
+
154
+ 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
163
+ end
164
+ end
152
165
  end
@@ -6,24 +6,30 @@ module Embulk
6
6
  def initialize(src)
7
7
  super
8
8
 
9
- record_reader_script = "lambda do |reader|\n"
10
- record_reader_script << "record = []\n"
9
+ record_reader_script =
10
+ "lambda do |reader|\n" <<
11
+ "record = []\n"
11
12
  each do |column|
13
+ idx = column.index
12
14
  column_script =
15
+ "if reader.isNull(#{idx})\n" <<
16
+ "record << nil\n" <<
17
+ "else\n" <<
13
18
  case column.type
14
19
  when :boolean
15
- "record << reader.getBoolean(#{column.index})"
20
+ "record << reader.getBoolean(#{idx})"
16
21
  when :long
17
- "record << reader.getLong(#{column.index})"
22
+ "record << reader.getLong(#{idx})"
18
23
  when :double
19
- "record << reader.getDouble(#{column.index})"
24
+ "record << reader.getDouble(#{idx})"
20
25
  when :string
21
- "record << reader.getString(#{column.index})"
26
+ "record << reader.getString(#{idx})"
22
27
  when :timestamp
23
- "record << reader.getTimestamp(#{column.index}).getRubyTime(JRuby.runtime)"
28
+ "record << reader.getTimestamp(#{idx}).getRubyTime(JRuby.runtime)"
24
29
  else
25
30
  raise "Unknown type #{column.type.inspect}"
26
- end
31
+ end <<
32
+ "end\n"
27
33
  record_reader_script << column_script << "\n"
28
34
  end
29
35
  record_reader_script << "record\n"
@@ -34,7 +40,8 @@ module Embulk
34
40
  record_writer_script << "java_timestamp_class = ::Embulk::Java::Timestamp\n"
35
41
  each do |column|
36
42
  idx = column.index
37
- column_script = "if record[#{idx}].nil?\n" <<
43
+ column_script =
44
+ "if record[#{idx}].nil?\n" <<
38
45
  "builder.setNull(#{idx})\n" <<
39
46
  "else\n" <<
40
47
  case column.type
@@ -1,3 +1,3 @@
1
1
  module Embulk
2
- VERSION = "0.2.1"
2
+ VERSION = "0.3.0"
3
3
  end
data/pom.xml CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  <groupId>org.embulk</groupId>
6
6
  <artifactId>embulk-parent</artifactId>
7
- <version>0.2.1-SNAPSHOT</version>
7
+ <version>0.3.0-SNAPSHOT</version>
8
8
  <packaging>pom</packaging>
9
9
 
10
10
  <name>Embulk</name>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: embulk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sadayuki Furuhashi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-29 00:00:00.000000000 Z
11
+ date: 2015-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -122,9 +122,9 @@ files:
122
122
  - classpath/commons-codec-1.3.jar
123
123
  - classpath/commons-lang3-3.1.jar
124
124
  - classpath/commons-logging-1.2.jar
125
- - classpath/embulk-cli-0.2.1-SNAPSHOT.jar
126
- - classpath/embulk-core-0.2.1-SNAPSHOT.jar
127
- - classpath/embulk-standards-0.2.1-SNAPSHOT.jar
125
+ - classpath/embulk-cli-0.3.0-SNAPSHOT.jar
126
+ - classpath/embulk-core-0.3.0-SNAPSHOT.jar
127
+ - classpath/embulk-standards-0.3.0-SNAPSHOT.jar
128
128
  - classpath/guava-17.0.jar
129
129
  - classpath/guice-3.0.jar
130
130
  - classpath/guice-multibindings-3.0.jar
@@ -177,18 +177,20 @@ files:
177
177
  - embulk-core/src/main/java/org/embulk/config/TaskValidationException.java
178
178
  - embulk-core/src/main/java/org/embulk/config/TaskValidator.java
179
179
  - embulk-core/src/main/java/org/embulk/exec/ExecModule.java
180
- - embulk-core/src/main/java/org/embulk/exec/ExecuteInterruptedException.java
181
- - embulk-core/src/main/java/org/embulk/exec/ExecuteResult.java
180
+ - embulk-core/src/main/java/org/embulk/exec/ExecutionInterruptedException.java
181
+ - embulk-core/src/main/java/org/embulk/exec/ExecutionResult.java
182
182
  - embulk-core/src/main/java/org/embulk/exec/ExtensionServiceLoaderModule.java
183
183
  - embulk-core/src/main/java/org/embulk/exec/ForSystemConfig.java
184
184
  - embulk-core/src/main/java/org/embulk/exec/GuessExecutor.java
185
185
  - embulk-core/src/main/java/org/embulk/exec/LocalExecutor.java
186
186
  - embulk-core/src/main/java/org/embulk/exec/LoggerProvider.java
187
187
  - embulk-core/src/main/java/org/embulk/exec/NoSampleException.java
188
+ - embulk-core/src/main/java/org/embulk/exec/PartialExecutionException.java
188
189
  - embulk-core/src/main/java/org/embulk/exec/PooledBufferAllocator.java
189
190
  - embulk-core/src/main/java/org/embulk/exec/PreviewExecutor.java
190
191
  - embulk-core/src/main/java/org/embulk/exec/PreviewResult.java
191
192
  - embulk-core/src/main/java/org/embulk/exec/PreviewedNoticeError.java
193
+ - embulk-core/src/main/java/org/embulk/exec/ResumeState.java
192
194
  - embulk-core/src/main/java/org/embulk/exec/SamplingParserPlugin.java
193
195
  - embulk-core/src/main/java/org/embulk/exec/SystemConfigModule.java
194
196
  - embulk-core/src/main/java/org/embulk/jruby/JRubyPluginSource.java
@@ -216,6 +218,7 @@ files:
216
218
  - embulk-core/src/main/java/org/embulk/spi/FileOutput.java
217
219
  - embulk-core/src/main/java/org/embulk/spi/FileOutputPlugin.java
218
220
  - embulk-core/src/main/java/org/embulk/spi/FileOutputRunner.java
221
+ - embulk-core/src/main/java/org/embulk/spi/FilterPlugin.java
219
222
  - embulk-core/src/main/java/org/embulk/spi/FormatterPlugin.java
220
223
  - embulk-core/src/main/java/org/embulk/spi/GuessPlugin.java
221
224
  - embulk-core/src/main/java/org/embulk/spi/InputPlugin.java
@@ -256,6 +259,7 @@ files:
256
259
  - embulk-core/src/main/java/org/embulk/spi/util/Encoders.java
257
260
  - embulk-core/src/main/java/org/embulk/spi/util/FileInputInputStream.java
258
261
  - embulk-core/src/main/java/org/embulk/spi/util/FileOutputOutputStream.java
262
+ - embulk-core/src/main/java/org/embulk/spi/util/Filters.java
259
263
  - embulk-core/src/main/java/org/embulk/spi/util/InputStreamFileInput.java
260
264
  - embulk-core/src/main/java/org/embulk/spi/util/Inputs.java
261
265
  - embulk-core/src/main/java/org/embulk/spi/util/LineDecoder.java
@@ -320,10 +324,12 @@ files:
320
324
  - lib/embulk/data/bundle/.bundle/config
321
325
  - lib/embulk/data/bundle/Gemfile
322
326
  - lib/embulk/data/bundle/Gemfile.lock
327
+ - lib/embulk/data/bundle/embulk/filter_example.rb
323
328
  - lib/embulk/data/bundle/embulk/input_example.rb
324
329
  - lib/embulk/data/bundle/embulk/output_example.rb
325
330
  - lib/embulk/data_source.rb
326
331
  - lib/embulk/error.rb
332
+ - lib/embulk/filter_plugin.rb
327
333
  - lib/embulk/guess_charset.rb
328
334
  - lib/embulk/guess_csv.rb
329
335
  - lib/embulk/guess_gzip.rb