embulk 0.6.21 → 0.6.22

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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/build.gradle +27 -15
  4. data/embulk-core/build.gradle +17 -1
  5. data/embulk-core/src/main/java/org/embulk/EmbulkEmbed.java +216 -0
  6. data/embulk-core/src/main/java/org/embulk/EmbulkService.java +13 -7
  7. data/embulk-core/src/main/java/org/embulk/command/LiquidTemplate.java +8 -0
  8. data/embulk-core/src/main/java/org/embulk/command/Runner.java +63 -27
  9. data/embulk-core/src/main/java/org/embulk/config/ConfigLoader.java +5 -0
  10. data/embulk-core/src/main/java/org/embulk/config/DataSourceImpl.java +3 -3
  11. data/embulk-core/src/main/java/org/embulk/exec/ExecModule.java +1 -1
  12. data/embulk-core/src/main/java/org/embulk/exec/PooledBufferAllocator.java +3 -1
  13. data/embulk-core/src/main/java/org/embulk/guice/Bootstrap.java +150 -0
  14. data/embulk-core/src/main/java/org/embulk/guice/CloseableInjector.java +22 -0
  15. data/embulk-core/src/main/java/org/embulk/guice/CloseableInjectorProxy.java +47 -0
  16. data/embulk-core/src/main/java/org/embulk/guice/InjectorProxy.java +145 -0
  17. data/embulk-core/src/main/java/org/embulk/guice/LifeCycleManager.java +187 -0
  18. data/embulk-core/src/main/java/org/embulk/guice/LifeCycleMethods.java +89 -0
  19. data/embulk-core/src/main/java/org/embulk/guice/LifeCycleMethodsMap.java +38 -0
  20. data/embulk-core/src/main/java/org/embulk/guice/LifeCycleModule.java +97 -0
  21. data/embulk-core/src/main/java/org/embulk/spi/TempFileSpace.java +41 -7
  22. data/embulk-docs/build.gradle +3 -2
  23. data/embulk-docs/src/built-in.rst +30 -1
  24. data/embulk-docs/src/index.rst +1 -1
  25. data/embulk-docs/src/release.rst +1 -0
  26. data/embulk-docs/src/release/release-0.6.22.rst +26 -0
  27. data/gradle/wrapper/gradle-wrapper.jar +0 -0
  28. data/gradle/wrapper/gradle-wrapper.properties +2 -2
  29. data/lib/embulk/command/embulk_run.rb +11 -5
  30. data/lib/embulk/data_source.rb +28 -8
  31. data/lib/embulk/error.rb +7 -1
  32. data/lib/embulk/gems.rb +29 -0
  33. data/lib/embulk/java/bootstrap.rb +4 -0
  34. data/lib/embulk/java/liquid_helper.rb +17 -0
  35. data/lib/embulk/version.rb +1 -1
  36. data/test/helper.rb +11 -2
  37. metadata +46 -33
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 90d6280d5bdcffb92922bfd929eae4bcc6d83b92
4
- data.tar.gz: 0e2c0d5e8a9f990cdfbb7006be196f9bfef19030
3
+ metadata.gz: 9517ba89a58e4c0980976822f7508f0b1040ea6c
4
+ data.tar.gz: dc378ef610b2e1cab1d4b66eb3ff46b64e0817bf
5
5
  SHA512:
6
- metadata.gz: e2ccbee9c830dd29e86734c1615354083fca35068476a30d0a06944926c3eb63b0386ab5db39d0ad7ed660a2c395da84e68d8433ee222274102dc01b30312de6
7
- data.tar.gz: 27174e4750c66516ead7b0ff90df6dc804e8d45694354cd03602654680b30dd0464fef0221aa18a9c28e6495ad6709e44e0c4469b12e55f3ca81d8b1bdb06fdc
6
+ metadata.gz: 07bd4d4bd1688835f9c830dab95206d7343c0c183427472842106f341d26feea84189f032499dbb1d5c955ae88a348fd806a09003b8fc0b46cd14e41fadf94de
7
+ data.tar.gz: 976b17fa42e6ba9dd0c02506097af5a0ac32b50155024a70cd9fa831f905ab5909caa9b0fec62ce96f86fd347271d8d39587e99d2a39805287280b42d4480695
data/.gitignore CHANGED
@@ -12,3 +12,4 @@ vendor/
12
12
  .yardoc
13
13
  /embulk-*.jar
14
14
  /.gradle
15
+ /coverage
@@ -1,20 +1,25 @@
1
-
2
- plugins {
3
- id 'com.jfrog.bintray' version '1.1'
4
- id 'com.github.ben-manes.versions' version '0.7'
5
- id 'com.github.jruby-gradle.base' version '0.1.5'
6
- id 'com.github.johnrengelman.shadow' version '1.2.0'
1
+ buildscript {
2
+ repositories { jcenter() }
3
+ dependencies {
4
+ classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.3.1'
5
+ classpath "com.github.jruby-gradle:jruby-gradle-jar-plugin:1.0.1"
6
+ classpath 'com.github.ben-manes:gradle-versions-plugin:0.11.3'
7
+ classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.2'
8
+ }
7
9
  }
10
+ apply plugin: "com.github.jruby-gradle.jar"
11
+ apply plugin: 'com.jfrog.bintray'
12
+ apply plugin: 'com.github.johnrengelman.shadow'
8
13
 
9
14
  def java_projects = [project(":embulk-core"), project(":embulk-standards"), project(":embulk-cli")]
10
15
  def release_projects = [project(":embulk-core"), project(":embulk-standards")]
11
16
 
12
17
  allprojects {
13
18
  group = 'org.embulk'
14
- version = '0.6.21'
19
+ version = '0.6.22'
15
20
 
16
21
  ext {
17
- jrubyVersion = '1.7.19'
22
+ jrubyVersion = '1.7.21'
18
23
  }
19
24
 
20
25
  apply plugin: 'java'
@@ -140,12 +145,17 @@ subprojects {
140
145
  }
141
146
  }
142
147
 
148
+ task wrapper(type: Wrapper) {
149
+ gradleVersion = '2.6'
150
+ }
151
+
143
152
  import com.github.jrubygradle.JRubyExec
144
153
  jruby {
145
154
  execVersion = project.jrubyVersion
146
155
  }
147
156
 
148
157
  dependencies {
158
+ jrubyExec 'rubygems:simplecov:0.10.+'
149
159
  jrubyExec 'rubygems:test-unit:3.0.+'
150
160
  }
151
161
 
@@ -226,8 +236,8 @@ project(':embulk-cli') {
226
236
  }
227
237
 
228
238
  task rubyTest(type: JRubyExec) {
229
- jrubyArgs '-Ilib', '-Itest', '-rtest/unit', '-eTest::Unit::AutoRunner.run(true, *ARGV)'
230
- script 'test'
239
+ jrubyArgs '-Ilib', '-Itest', '-rtest/unit', '--debug', '-eARGV.replace([]); Test::Unit::AutoRunner.run(true, "test")'
240
+ script './lib/embulk/version.rb' // dummy
231
241
  }
232
242
  rubyTest.dependsOn('classpath')
233
243
 
@@ -235,9 +245,10 @@ rubyTest.dependsOn('classpath')
235
245
  // gem task
236
246
  //
237
247
  task gem(type: JRubyExec) {
238
- jrubyArgs '-rrubygems/gem_runner', '-eGem::GemRunner.new.run(ARGV)', 'build'
239
- script 'embulk.gemspec'
240
- doLast { ant.move(file: "${project.name}-${project.version}.gem", todir: "pkg") }
248
+ jrubyArgs '-rrubygems/gem_runner', '-eGem::GemRunner.new.run(ARGV)'
249
+ script './lib/embulk/version.rb' // dummy
250
+ scriptArgs 'build', 'embulk.gemspec'
251
+ doLast { file("${project.name}-${project.version}.gem").renameTo("pkg/${project.name}-${project.version}.gem") }
241
252
  }
242
253
  gem.dependsOn('classpath')
243
254
 
@@ -245,8 +256,9 @@ gem.dependsOn('classpath')
245
256
  // rubyGemsUpload task
246
257
  //
247
258
  task rubyGemsUpload(type: JRubyExec, dependsOn: ["gem"]) {
248
- jrubyArgs '-rrubygems/gem_runner', '-eGem::GemRunner.new.run(ARGV)', 'push'
249
- script "pkg/embulk-${project.version}.gem"
259
+ jrubyArgs '-rrubygems/gem_runner', '-eGem::GemRunner.new.run(ARGV)'
260
+ script './lib/embulk/version.rb' // dummy
261
+ scriptArgs 'push', "pkg/embulk-${project.version}.gem"
250
262
  }
251
263
 
252
264
  //
@@ -1,6 +1,8 @@
1
+ apply plugin: "com.github.jruby-gradle.jar"
2
+
1
3
  // include ruby scripts to jar. don't use sourceSets.main.resources.srcDirs
2
4
  // because IntelliJ causes error if srcDirs includes files out of projectDir.
3
- processResources.from "${rootProject.projectDir}/lib"
5
+ processResources.from("${rootProject.projectDir}/lib", "${buildDir}/jruby")
4
6
 
5
7
  configurations {
6
8
  // com.google.inject:guice depends on asm and cglib but version of the libraries conflict
@@ -9,6 +11,9 @@ configurations {
9
11
  compile.exclude group: 'org.sonatype.sisu.inject', module: 'cglib'
10
12
  }
11
13
 
14
+ import com.github.jrubygradle.JRubyExec
15
+ import com.github.jrubygradle.JRubyPrepare
16
+
12
17
  // determine which dependencies have updates: $ gradle dependencyUpdates
13
18
  dependencies {
14
19
  compile 'com.google.guava:guava:18.0'
@@ -35,4 +40,15 @@ dependencies {
35
40
 
36
41
  // for embulk/guess/charset.rb
37
42
  compile 'com.ibm.icu:icu4j:54.1.1'
43
+
44
+ gems 'rubygems:liquid:3.0.6'
45
+ }
46
+
47
+ task unpackGems(type: JRubyPrepare) {
48
+ outputDir file("${buildDir}/jruby/embulk/gems")
49
+ dependencies configurations.gems
50
+ doLast {
51
+ fileTree(dir: "${buildDir}/jruby/embulk/gems/cache", include: "*.gem").each { f -> f.delete() }
52
+ }
38
53
  }
54
+ processResources.dependsOn("unpackGems")
@@ -0,0 +1,216 @@
1
+ package org.embulk;
2
+
3
+ import java.util.Arrays;
4
+ import java.util.List;
5
+ import com.google.common.base.Function;
6
+ import com.google.common.base.Throwables;
7
+ import com.google.common.collect.ImmutableList;
8
+ import com.google.common.collect.Iterables;
9
+ import com.google.common.annotations.Beta;
10
+ import com.google.inject.Injector;
11
+ import com.google.inject.Module;
12
+ import com.fasterxml.jackson.databind.ObjectMapper;
13
+ import org.embulk.config.ModelManager;
14
+ import org.embulk.config.ConfigSource;
15
+ import org.embulk.config.ConfigDiff;
16
+ import org.embulk.config.ConfigLoader;
17
+ import org.embulk.EmbulkService;
18
+ import org.embulk.exec.BulkLoader;
19
+ import org.embulk.exec.GuessExecutor;
20
+ import org.embulk.exec.PreviewExecutor;
21
+ import org.embulk.exec.PreviewResult;
22
+ import org.embulk.exec.ExecutionResult;
23
+ import org.embulk.exec.PartialExecutionException;
24
+ import org.embulk.exec.ResumeState;
25
+ import org.embulk.spi.ExecSession;
26
+ import org.embulk.guice.Bootstrap;
27
+ import org.embulk.guice.CloseableInjector;
28
+ import static com.google.common.base.Preconditions.checkState;
29
+ import static com.google.common.base.Preconditions.checkNotNull;
30
+
31
+ @Beta
32
+ public class EmbulkEmbed
33
+ implements AutoCloseable
34
+ {
35
+ public static ConfigLoader newSystemConfigLoader()
36
+ {
37
+ return new ConfigLoader(new ModelManager(null, new ObjectMapper()));
38
+ }
39
+
40
+ private final CloseableInjector injector;
41
+ private final BulkLoader bulkLoader;
42
+ private final GuessExecutor guessExecutor;
43
+ private final PreviewExecutor previewExecutor;
44
+
45
+ public EmbulkEmbed(ConfigSource systemConfig, Module... additionalModules)
46
+ {
47
+ this(systemConfig, Arrays.asList(additionalModules));
48
+ }
49
+
50
+ public EmbulkEmbed(ConfigSource systemConfig,
51
+ final Iterable<? extends Module> additionalModules)
52
+ {
53
+ this(systemConfig,
54
+ new Function<List<Module>, Iterable<Module>>()
55
+ {
56
+ public Iterable<Module> apply(List<Module> source)
57
+ {
58
+ return Iterables.concat(source, additionalModules);
59
+ }
60
+ });
61
+ }
62
+
63
+ public EmbulkEmbed(ConfigSource systemConfig,
64
+ Function<? super List<Module>, ? extends Iterable<? extends Module>> overrideModules)
65
+ {
66
+ this.injector = new Bootstrap()
67
+ .requireExplicitBindings(false)
68
+ .addModules(EmbulkService.standardModuleList(systemConfig))
69
+ .overrideModules(overrideModules)
70
+ .initializeCloseable();
71
+ injector.getInstance(org.slf4j.ILoggerFactory.class);
72
+ this.bulkLoader = new BulkLoader(injector, systemConfig);
73
+ this.guessExecutor = injector.getInstance(GuessExecutor.class);
74
+ this.previewExecutor = injector.getInstance(PreviewExecutor.class);
75
+ }
76
+
77
+ @Override
78
+ public void close()
79
+ {
80
+ try {
81
+ injector.close();
82
+ }
83
+ catch (Exception ex) {
84
+ throw Throwables.propagate(ex);
85
+ }
86
+ }
87
+
88
+ public Injector getInjector()
89
+ {
90
+ return injector;
91
+ }
92
+
93
+ public ModelManager getModelManager()
94
+ {
95
+ return injector.getInstance(ModelManager.class);
96
+ }
97
+
98
+ public ConfigLoader newConfigLoader()
99
+ {
100
+ return injector.getInstance(ConfigLoader.class);
101
+ }
102
+
103
+ public ExecSession.Builder sessionBuilder(ConfigSource execConfig)
104
+ {
105
+ return ExecSession.builder(injector).fromExecConfig(execConfig);
106
+ }
107
+
108
+ public ConfigDiff guess(ExecSession exec, ConfigSource config)
109
+ {
110
+ return guessExecutor.guess(exec, config);
111
+ }
112
+
113
+ public PreviewResult preview(ExecSession exec, ConfigSource config)
114
+ {
115
+ return previewExecutor.preview(exec, config);
116
+ }
117
+
118
+ public ExecutionResult run(ExecSession exec, ConfigSource config)
119
+ {
120
+ try {
121
+ return bulkLoader.run(exec, config);
122
+ } catch (PartialExecutionException partial) {
123
+ try {
124
+ bulkLoader.cleanup(config, partial.getResumeState());
125
+ } catch (Throwable ex) {
126
+ partial.addSuppressed(ex);
127
+ }
128
+ throw partial;
129
+ }
130
+ }
131
+
132
+ public ResumableResult runResumable(ExecSession exec, ConfigSource config)
133
+ {
134
+ ExecutionResult result;
135
+ try {
136
+ result = bulkLoader.run(exec, config);
137
+ } catch (PartialExecutionException partial) {
138
+ return new ResumableResult(partial);
139
+ }
140
+ return new ResumableResult(result);
141
+ }
142
+
143
+ public ResumeAction resumeAction(ConfigSource config, ResumeState resumeState)
144
+ {
145
+ return new ResumeAction(config, resumeState);
146
+ }
147
+
148
+ public static class ResumableResult
149
+ {
150
+ private final ExecutionResult successfulResult;
151
+ private final PartialExecutionException partialExecutionException;
152
+
153
+ public ResumableResult(PartialExecutionException partialExecutionException)
154
+ {
155
+ this.successfulResult = null;
156
+ this.partialExecutionException = checkNotNull(partialExecutionException);
157
+ }
158
+
159
+ public ResumableResult(ExecutionResult successfulResult)
160
+ {
161
+ this.successfulResult = checkNotNull(successfulResult);
162
+ this.partialExecutionException = null;
163
+ }
164
+
165
+ public boolean isSuccessful()
166
+ {
167
+ return successfulResult != null;
168
+ }
169
+
170
+ public ExecutionResult getSuccessfulResult()
171
+ {
172
+ checkState(successfulResult != null);
173
+ return successfulResult;
174
+ }
175
+
176
+ public Throwable getCause()
177
+ {
178
+ checkState(partialExecutionException != null);
179
+ return partialExecutionException.getCause();
180
+ }
181
+
182
+ public ResumeState getResumeState()
183
+ {
184
+ checkState(partialExecutionException != null);
185
+ return partialExecutionException.getResumeState();
186
+ }
187
+ }
188
+
189
+ public class ResumeAction
190
+ {
191
+ private final ConfigSource config;
192
+ private final ResumeState resumeState;
193
+
194
+ public ResumeAction(ConfigSource config, ResumeState resumeState)
195
+ {
196
+ this.config = config;
197
+ this.resumeState = resumeState;
198
+ }
199
+
200
+ public ResumableResult resume()
201
+ {
202
+ ExecutionResult result;
203
+ try {
204
+ result = bulkLoader.resume(config, resumeState);
205
+ } catch (PartialExecutionException partial) {
206
+ return new ResumableResult(partial);
207
+ }
208
+ return new ResumableResult(result);
209
+ }
210
+
211
+ public void cleanup()
212
+ {
213
+ bulkLoader.cleanup(config, resumeState);
214
+ }
215
+ }
216
+ }
@@ -1,5 +1,6 @@
1
1
  package org.embulk;
2
2
 
3
+ import java.util.List;
3
4
  import com.google.common.collect.ImmutableList;
4
5
  import com.google.inject.Guice;
5
6
  import com.google.inject.Injector;
@@ -35,18 +36,23 @@ public class EmbulkService
35
36
  return modules;
36
37
  }
37
38
 
39
+ static List<Module> standardModuleList(ConfigSource systemConfig)
40
+ {
41
+ return ImmutableList.of(
42
+ new SystemConfigModule(systemConfig),
43
+ new ExecModule(),
44
+ new ExtensionServiceLoaderModule(systemConfig),
45
+ new PluginClassLoaderModule(systemConfig),
46
+ new BuiltinPluginSourceModule(),
47
+ new JRubyScriptingModule(systemConfig));
48
+ }
49
+
38
50
  public Injector initialize()
39
51
  {
40
52
  checkState(!initialized, "Already initialized");
41
53
 
42
54
  ImmutableList.Builder<Module> builder = ImmutableList.builder();
43
- builder.add(new SystemConfigModule(systemConfig));
44
- builder.add(new ExecModule());
45
- builder.add(new ExtensionServiceLoaderModule(systemConfig));
46
- builder.add(new PluginClassLoaderModule(systemConfig));
47
- builder.add(new BuiltinPluginSourceModule());
48
- builder.add(new JRubyScriptingModule(systemConfig));
49
-
55
+ builder.addAll(standardModuleList(systemConfig));
50
56
  builder.addAll(getAdditionalModules(systemConfig));
51
57
 
52
58
  Iterable<? extends Module> modules = builder.build();
@@ -0,0 +1,8 @@
1
+ package org.embulk.command;
2
+
3
+ import java.util.Map;
4
+
5
+ public interface LiquidTemplate
6
+ {
7
+ public String render(String source, Map<String, String> params);
8
+ }
@@ -10,10 +10,15 @@ import java.io.FileOutputStream;
10
10
  import java.io.BufferedWriter;
11
11
  import java.io.OutputStreamWriter;
12
12
  import java.io.Writer;
13
+ import java.io.ByteArrayInputStream;
14
+ import java.nio.charset.StandardCharsets;
13
15
  import org.yaml.snakeyaml.Yaml;
14
16
  import com.fasterxml.jackson.databind.ObjectMapper;
15
17
  import com.google.common.base.Function;
18
+ import com.google.common.collect.ImmutableMap;
19
+ import com.google.common.io.Files;
16
20
  import com.google.inject.Injector;
21
+ import org.jruby.embed.ScriptingContainer;
17
22
  import org.embulk.config.ConfigSource;
18
23
  import org.embulk.config.DataSource;
19
24
  import org.embulk.config.ConfigLoader;
@@ -30,7 +35,7 @@ import org.embulk.exec.ResumeState;
30
35
  import org.embulk.exec.PartialExecutionException;
31
36
  import org.embulk.spi.time.Timestamp;
32
37
  import org.embulk.spi.ExecSession;
33
- import org.embulk.EmbulkService;
38
+ import org.embulk.EmbulkEmbed;
34
39
 
35
40
  public class Runner
36
41
  {
@@ -60,8 +65,9 @@ public class Runner
60
65
 
61
66
  private final Options options;
62
67
  private final ConfigSource systemConfig;
63
- private final EmbulkService service;
64
- private final Injector injector;
68
+
69
+ private EmbulkEmbed embed;
70
+ private Injector injector;
65
71
 
66
72
  public Runner(String optionJson)
67
73
  {
@@ -73,8 +79,6 @@ public class Runner
73
79
  mergeOptionsToSystemConfig(options, configLoader, systemConfig);
74
80
 
75
81
  this.systemConfig = systemConfig;
76
- this.service = new EmbulkService(systemConfig);
77
- this.injector = service.initialize();
78
82
  }
79
83
 
80
84
  @SuppressWarnings("unchecked")
@@ -105,27 +109,31 @@ public class Runner
105
109
 
106
110
  public void main(String command, String[] args)
107
111
  {
108
- switch (command) {
109
- case "run":
110
- run(args[0]);
111
- break;
112
- case "cleanup":
113
- cleanup(args[0]);
114
- break;
115
- case "guess":
116
- guess(args[0]);
117
- break;
118
- case "preview":
119
- preview(args[0]);
120
- break;
121
- default:
122
- throw new RuntimeException("Unsupported command: "+command);
112
+ try (EmbulkEmbed embed = new EmbulkEmbed(systemConfig)) {
113
+ this.injector = embed.getInjector();
114
+
115
+ switch (command) {
116
+ case "run":
117
+ run(args[0]);
118
+ break;
119
+ case "cleanup":
120
+ cleanup(args[0]);
121
+ break;
122
+ case "guess":
123
+ guess(args[0]);
124
+ break;
125
+ case "preview":
126
+ preview(args[0]);
127
+ break;
128
+ default:
129
+ throw new RuntimeException("Unsupported command: "+command);
130
+ }
123
131
  }
124
132
  }
125
133
 
126
134
  public void run(String configPath)
127
135
  {
128
- ConfigSource config = loadYamlConfig(configPath);
136
+ ConfigSource config = loadConfig(configPath);
129
137
  checkFileWritable(options.getNextConfigOutputPath());
130
138
  checkFileWritable(options.getResumeStatePath());
131
139
 
@@ -199,7 +207,7 @@ public class Runner
199
207
  if (resumePath == null) {
200
208
  throw new IllegalArgumentException("Resume path is required for cleanup");
201
209
  }
202
- ConfigSource config = loadYamlConfig(configPath);
210
+ ConfigSource config = loadConfig(configPath);
203
211
  ConfigSource resumeConfig = loadYamlConfig(resumePath);
204
212
  ResumeState resume = resumeConfig.loadConfig(ResumeState.class);
205
213
 
@@ -212,7 +220,7 @@ public class Runner
212
220
 
213
221
  public void guess(String partialConfigPath)
214
222
  {
215
- ConfigSource config = loadYamlConfig(partialConfigPath);
223
+ ConfigSource config = loadConfig(partialConfigPath);
216
224
  checkFileWritable(options.getNextConfigOutputPath());
217
225
 
218
226
  ConfigDiff configDiff;
@@ -268,7 +276,7 @@ public class Runner
268
276
  {
269
277
  PreviewResult result;
270
278
  {
271
- ConfigSource config = loadYamlConfig(partialConfigPath);
279
+ ConfigSource config = loadConfig(partialConfigPath);
272
280
  ExecSession exec = newExecSession(config);
273
281
  try {
274
282
  PreviewExecutor preview = injector.getInstance(PreviewExecutor.class);
@@ -304,12 +312,40 @@ public class Runner
304
312
  }
305
313
  }
306
314
 
307
- private ConfigSource loadYamlConfig(String yamlPath)
315
+ private ConfigSource loadConfig(String path)
316
+ {
317
+ if (path.endsWith(".yml") || path.endsWith(".yaml")) {
318
+ return loadYamlConfig(path);
319
+ }
320
+ else if (path.endsWith(".yml.liquid") || path.endsWith(".yaml.liquid")) {
321
+ return loadLiquidYamlConfig(path);
322
+ }
323
+ else {
324
+ throw new ConfigException("Unknown file extension. Supported file extentions are .yml and .yml.liquid: "+path);
325
+ }
326
+ }
327
+
328
+ private ConfigSource loadYamlConfig(String path)
308
329
  {
309
330
  try {
310
- return injector.getInstance(ConfigLoader.class).fromYamlFile(new File(yamlPath));
331
+ return injector.getInstance(ConfigLoader.class).fromYamlFile(new File(path));
332
+ }
333
+ catch (IOException ex) {
334
+ throw new ConfigException(ex);
335
+ }
336
+ }
311
337
 
312
- } catch (IOException ex) {
338
+ private ConfigSource loadLiquidYamlConfig(String path)
339
+ {
340
+ LiquidTemplate helper = (LiquidTemplate) injector.getInstance(ScriptingContainer.class).runScriptlet("Embulk::Java::LiquidTemplateHelper.new");
341
+ try {
342
+ String source = Files.toString(new File(path), StandardCharsets.UTF_8);
343
+ String data = helper.render(source, ImmutableMap.<String,String>of());
344
+ try (ByteArrayInputStream in = new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8))) {
345
+ return injector.getInstance(ConfigLoader.class).fromYaml(in);
346
+ }
347
+ }
348
+ catch (IOException ex) {
313
349
  throw new ConfigException(ex);
314
350
  }
315
351
  }