embulk 0.6.21 → 0.6.22

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,89 @@
1
+ /*
2
+ * Copyright 2010 Proofpoint, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ /*
17
+ * Copyright 2015 Sadayuki Furuhashi
18
+ */
19
+ package org.embulk.guice;
20
+
21
+ import com.google.common.collect.ArrayListMultimap;
22
+ import com.google.common.collect.Lists;
23
+ import com.google.common.collect.Multimap;
24
+
25
+ import javax.annotation.PostConstruct;
26
+ import javax.annotation.PreDestroy;
27
+ import java.lang.annotation.Annotation;
28
+ import java.lang.reflect.Method;
29
+ import java.util.Collection;
30
+ import java.util.HashSet;
31
+ import java.util.Set;
32
+
33
+ class LifeCycleMethods
34
+ {
35
+ private final Multimap<Class<? extends Annotation>, Method> methodMap = ArrayListMultimap.create();
36
+
37
+ LifeCycleMethods(Class<?> clazz)
38
+ {
39
+ addLifeCycleMethods(clazz, new HashSet<String>(), new HashSet<String>());
40
+ }
41
+
42
+ boolean hasFor(Class<? extends Annotation> annotation)
43
+ {
44
+ Collection<Method> methods = methodMap.get(annotation);
45
+ return (methods != null) && (methods.size() > 0);
46
+ }
47
+
48
+ Collection<Method> methodsFor(Class<? extends Annotation> annotation)
49
+ {
50
+ Collection<Method> methods = methodMap.get(annotation);
51
+ return (methods != null) ? methods : Lists.<Method>newArrayList();
52
+ }
53
+
54
+ private void addLifeCycleMethods(Class<?> clazz, Set<String> usedConstructNames, Set<String> usedDestroyNames)
55
+ {
56
+ if (clazz == null) {
57
+ return;
58
+ }
59
+
60
+ for (Method method : clazz.getDeclaredMethods()) {
61
+ if (method.isSynthetic() || method.isBridge()) {
62
+ continue;
63
+ }
64
+
65
+ processMethod(method, PostConstruct.class, usedConstructNames);
66
+ processMethod(method, PreDestroy.class, usedDestroyNames);
67
+ }
68
+
69
+ addLifeCycleMethods(clazz.getSuperclass(), usedConstructNames, usedDestroyNames);
70
+ for (Class<?> face : clazz.getInterfaces()) {
71
+ addLifeCycleMethods(face, usedConstructNames, usedDestroyNames);
72
+ }
73
+ }
74
+
75
+ private void processMethod(Method method, Class<? extends Annotation> annotationClass, Set<String> usedSet)
76
+ {
77
+ if (method.isAnnotationPresent(annotationClass)) {
78
+ if (!usedSet.contains(method.getName())) {
79
+ if (method.getParameterTypes().length != 0) {
80
+ throw new UnsupportedOperationException(String.format("@PostConstruct/@PreDestroy methods cannot have arguments: %s", method.getDeclaringClass().getName() + "." + method.getName() + "(...)"));
81
+ }
82
+
83
+ method.setAccessible(true);
84
+ usedSet.add(method.getName());
85
+ methodMap.put(annotationClass, method);
86
+ }
87
+ }
88
+ }
89
+ }
@@ -0,0 +1,38 @@
1
+ /*
2
+ * Copyright 2010 Proofpoint, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ /*
17
+ * Copyright 2015 Sadayuki Furuhashi
18
+ */
19
+ package org.embulk.guice;
20
+
21
+ import com.google.common.collect.Maps;
22
+
23
+ import java.util.Map;
24
+
25
+ class LifeCycleMethodsMap
26
+ {
27
+ private final Map<Class<?>, LifeCycleMethods> map = Maps.newHashMap();
28
+
29
+ synchronized LifeCycleMethods get(Class<?> clazz)
30
+ {
31
+ LifeCycleMethods methods = map.get(clazz);
32
+ if (methods == null) {
33
+ methods = new LifeCycleMethods(clazz);
34
+ map.put(clazz, methods);
35
+ }
36
+ return methods;
37
+ }
38
+ }
@@ -0,0 +1,97 @@
1
+ /*
2
+ * Copyright 2010 Proofpoint, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ /*
17
+ * Copyright 2015 Sadayuki Furuhashi
18
+ */
19
+ package org.embulk.guice;
20
+
21
+ import com.google.common.collect.Lists;
22
+ import com.google.inject.Binder;
23
+ import com.google.inject.Module;
24
+ import com.google.inject.Provides;
25
+ import com.google.inject.Singleton;
26
+ import com.google.inject.TypeLiteral;
27
+ import com.google.inject.spi.InjectionListener;
28
+ import com.google.inject.spi.TypeEncounter;
29
+ import com.google.inject.spi.TypeListener;
30
+
31
+ import javax.annotation.PostConstruct;
32
+ import javax.annotation.PreDestroy;
33
+ import java.util.List;
34
+ import java.util.concurrent.atomic.AtomicReference;
35
+
36
+ import static com.google.inject.matcher.Matchers.any;
37
+
38
+ /**
39
+ * Guice module for binding the LifeCycle manager
40
+ */
41
+ public class LifeCycleModule implements Module
42
+ {
43
+ private final List<Object> injectedInstances = Lists.newArrayList();
44
+ private final LifeCycleMethodsMap lifeCycleMethodsMap = new LifeCycleMethodsMap();
45
+ private final AtomicReference<LifeCycleManager> lifeCycleManagerRef = new AtomicReference<LifeCycleManager>(null);
46
+
47
+ @Override
48
+ public void configure(Binder binder)
49
+ {
50
+ binder.disableCircularProxies();
51
+
52
+ binder.bindListener(any(), new TypeListener()
53
+ {
54
+ @Override
55
+ public <T> void hear(TypeLiteral<T> type, TypeEncounter<T> encounter)
56
+ {
57
+ encounter.register(new InjectionListener<T>()
58
+ {
59
+ @Override
60
+ public void afterInjection(T obj)
61
+ {
62
+ if (isLifeCycleClass(obj.getClass())) {
63
+ LifeCycleManager lifeCycleManager = lifeCycleManagerRef.get();
64
+ if (lifeCycleManager != null) {
65
+ try {
66
+ lifeCycleManager.addInstance(obj);
67
+ }
68
+ catch (Exception e) {
69
+ throw new Error(e);
70
+ }
71
+ }
72
+ else {
73
+ injectedInstances.add(obj);
74
+ }
75
+ }
76
+ }
77
+ });
78
+ }
79
+ });
80
+ }
81
+
82
+ @Provides
83
+ @Singleton
84
+ public LifeCycleManager getServerManager()
85
+ throws Exception
86
+ {
87
+ LifeCycleManager lifeCycleManager = new LifeCycleManager(injectedInstances, lifeCycleMethodsMap);
88
+ lifeCycleManagerRef.set(lifeCycleManager);
89
+ return lifeCycleManager;
90
+ }
91
+
92
+ private boolean isLifeCycleClass(Class<?> clazz)
93
+ {
94
+ LifeCycleMethods methods = lifeCycleMethodsMap.get(clazz);
95
+ return methods.hasFor(PostConstruct.class) || methods.hasFor(PreDestroy.class);
96
+ }
97
+ }
@@ -3,6 +3,11 @@ package org.embulk.spi;
3
3
  import java.util.List;
4
4
  import java.util.ArrayList;
5
5
  import java.util.Collections;
6
+ import java.nio.file.Files;
7
+ import java.nio.file.Path;
8
+ import java.nio.file.SimpleFileVisitor;
9
+ import java.nio.file.attribute.BasicFileAttributes;
10
+ import java.nio.file.FileVisitResult;
6
11
  import java.io.File;
7
12
  import java.io.IOException;
8
13
  import com.google.common.base.Preconditions;
@@ -43,14 +48,43 @@ public class TempFileSpace
43
48
 
44
49
  public void cleanup()
45
50
  {
46
- File[] files = dir.listFiles();
47
- if (files != null) {
48
- for (File e : files) {
49
- e.delete();
50
- // TODO delete directory recursively
51
- }
51
+ try {
52
+ deleteFilesIfExistsRecursively(dir);
53
+ }
54
+ catch (IOException ex) {
55
+ // ignore IOException
52
56
  }
53
- dir.delete();
54
57
  dirCreated = false;
55
58
  }
59
+
60
+ private void deleteFilesIfExistsRecursively(File dir)
61
+ throws IOException
62
+ {
63
+ Files.walkFileTree(dir.toPath(), new SimpleFileVisitor<Path>()
64
+ {
65
+ @Override
66
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
67
+ {
68
+ try {
69
+ Files.deleteIfExists(file);
70
+ }
71
+ catch (IOException ex) {
72
+ // ignore IOException
73
+ }
74
+ return FileVisitResult.CONTINUE;
75
+ }
76
+
77
+ @Override
78
+ public FileVisitResult postVisitDirectory(Path dir, IOException exc)
79
+ {
80
+ try {
81
+ Files.deleteIfExists(dir);
82
+ }
83
+ catch (IOException ex) {
84
+ // ignore IOException
85
+ }
86
+ return FileVisitResult.CONTINUE;
87
+ }
88
+ });
89
+ }
56
90
  }
@@ -23,8 +23,9 @@ task javadoc_html(type: Copy, dependsOn: [':embulk-core:javadoc']) {
23
23
 
24
24
  task rdoc_html(type: JRubyExec) {
25
25
  workingDir '..'
26
- jrubyArgs '-ryard', '-eYARD::CLI::Yardoc.run(*ARGV)', '--', '-o', 'embulk-docs/build/html/rdoc'
27
- script 'lib'
26
+ jrubyArgs '-ryard', '-eYARD::CLI::Yardoc.run(*ARGV)'
27
+ script './lib/embulk/version.rb' // dummy
28
+ scriptArgs 'lib', '-o', 'embulk-docs/build/html/rdoc'
28
29
  }
29
30
 
30
31
  task site(type: Copy, dependsOn: ['sphinx_html', 'rdoc_html', 'javadoc_html']) {
@@ -59,6 +59,35 @@ A configuration file consists of following sections:
59
59
  In many cases, what you need to write is **in:**, **out**: and **formatter** sections only because ``guess`` command guesses **parser** and **decoder** options for you. See also the `Quick Start <https://github.com/embulk/embulk#quick-start>`_.
60
60
 
61
61
 
62
+ Using variables
63
+ ~~~~~~~~~~~~~~~~~~
64
+
65
+ You can embed environment variables in configuration file using `Liquid template engine <http://liquidmarkup.org/>`_ (This is experimental feature. Behavior might change or be removed in future releases).
66
+
67
+ To use template engine, configuration file name must end with ``.yml.liquid``.
68
+
69
+ Environment variables are set to ``env`` variable.
70
+
71
+ .. code-block:: yaml
72
+
73
+ in:
74
+ type: file
75
+ path_prefix: {{ env.path_prefix }}
76
+ decoders:
77
+ - {type: gzip}
78
+ parser:
79
+ ...
80
+ out:
81
+ type: postgresql
82
+ host: {{ env.pg_host }}
83
+ port: {{ env.pg_port }}
84
+ user: {{ env.pg_user }}
85
+ password: "{{ env.pg_password }}"
86
+ database: embulk_load
87
+ mode: insert
88
+ table: {{ env.pg_table }}
89
+
90
+
62
91
  Local file input plugin
63
92
  ------------------
64
93
 
@@ -248,7 +277,7 @@ Options
248
277
  +====================+==========+===================================================+============================+
249
278
  | path\_prefix | string | Path prefix of the output files | required |
250
279
  +--------------------+----------+---------------------------------------------------+----------------------------+
251
- | sequence\_format | string | Format of the sequence number of the output files | ``%03d.%02d.`` by default |
280
+ | sequence\_format | string | Format of the sequence number of the output files | ``%03d.%02d.`` by default |
252
281
  +--------------------+----------+---------------------------------------------------+----------------------------+
253
282
  | file\_ext | string | Path suffix of the output files (e.g. ``"csv"``) | required |
254
283
  +--------------------+----------+---------------------------------------------------+----------------------------+
@@ -62,7 +62,7 @@ Documents
62
62
  * `Executor plugins <http://www.embulk.org/plugins/#executor>`_
63
63
 
64
64
  .. toctree::
65
- :maxdepth: 2
65
+ :maxdepth: 3
66
66
 
67
67
  built-in
68
68
 
@@ -4,6 +4,7 @@ Release Notes
4
4
  .. toctree::
5
5
  :maxdepth: 1
6
6
 
7
+ release/release-0.6.22
7
8
  release/release-0.6.21
8
9
  release/release-0.6.20
9
10
  release/release-0.6.19
@@ -0,0 +1,26 @@
1
+ Release 0.6.22
2
+ ==================================
3
+
4
+ General Changes
5
+ ------------------
6
+
7
+ * Added experimental support for Liquid template engine of configuration files. If configuration file name ends with ``.yml.liquid``, embulk runs embeds variables using Liquid template engine.
8
+
9
+ Ruby Plugin API
10
+ ------------------
11
+
12
+ * Added ``Embulk.require_classpath`` method to initialize plugin test environment (@cosmo0920++)
13
+ * ``Embulk::ConfigError`` extends ``org.embulk.config.ConfigException``.
14
+ * ``Embulk::DataSource`` raises ``Embulk::ConfigError`` instead of StandardError.
15
+
16
+ Java Plugin API
17
+ ------------------
18
+
19
+ * Added ``org.embulk.EmbulkEmbed`` to embed Embulk in an applications as a library.
20
+ * Added ``ConfigLoader.newConfigSource`` to create an empty ConfigSource.
21
+ * ``TempFileSpace.cleanup`` deletes files and directories recursively (@cosmo0920++)
22
+
23
+
24
+ Release Date
25
+ ------------------
26
+ 2015-08-11
@@ -1,6 +1,6 @@
1
- #Wed Feb 04 13:46:12 PST 2015
1
+ #Tue Aug 11 00:26:20 PDT 2015
2
2
  distributionBase=GRADLE_USER_HOME
3
3
  distributionPath=wrapper/dists
4
4
  zipStoreBase=GRADLE_USER_HOME
5
5
  zipStorePath=wrapper/dists
6
- distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-bin.zip
6
+ distributionUrl=https\://services.gradle.org/distributions/gradle-2.6-bin.zip
@@ -206,6 +206,8 @@ examples:
206
206
  args = 0..0
207
207
 
208
208
  when :gem
209
+ require 'embulk/gems'
210
+ Embulk.add_embedded_gem_path
209
211
  require 'rubygems/gem_runner'
210
212
  Gem::GemRunner.new.run argv
211
213
  exit 0
@@ -357,11 +359,7 @@ examples:
357
359
  java.lang.Class.forName('org.embulk.command.Runner')
358
360
  rescue java.lang.ClassNotFoundException
359
361
  # load classpath
360
- classpath_dir = Embulk.home('classpath')
361
- jars = Dir.entries(classpath_dir).select {|f| f =~ /\.jar$/ }.sort
362
- jars.each do |jar|
363
- require File.join(classpath_dir, jar)
364
- end
362
+ Embulk.require_classpath
365
363
  end
366
364
 
367
365
  setup_plugin_paths(plugin_paths)
@@ -390,6 +388,14 @@ examples:
390
388
  end
391
389
  end
392
390
 
391
+ def self.require_classpath
392
+ classpath_dir = Embulk.home("classpath")
393
+ jars = Dir.entries(classpath_dir).select{|f| f =~ /\.jar$/ }.sort
394
+ jars.each do |jar|
395
+ require File.join(classpath_dir, jar)
396
+ end
397
+ end
398
+
393
399
  def self.default_gem_home
394
400
  if RUBY_PLATFORM =~ /java/i
395
401
  user_home = java.lang.System.properties["user.home"]
@@ -142,31 +142,51 @@ module Embulk
142
142
  value =
143
143
  case type
144
144
  when :integer
145
- Integer(v)
145
+ begin
146
+ Integer(v)
147
+ rescue => e
148
+ raise ConfigError, e
149
+ end
146
150
  when :float
147
- Float(v)
151
+ begin
152
+ Float(v)
153
+ rescue => e
154
+ raise ConfigError, e
155
+ end
148
156
  when :string
149
- String(v).dup
157
+ begin
158
+ String(v).dup
159
+ rescue => e
160
+ raise ConfigError, e
161
+ end
150
162
  when :bool
151
- !!v # TODO validation
163
+ begin
164
+ !!v # TODO validation
165
+ rescue => e
166
+ raise ConfigError, e
167
+ end
152
168
  when :hash
153
- raise ArgumentError, "Invalid value for :hash" unless v.is_a?(Hash)
169
+ raise ConfigError, "Invalid value for :hash" unless v.is_a?(Hash)
154
170
  DataSource.new.merge!(v)
155
171
  when :array
156
- raise ArgumentError, "Invalid value for :array" unless v.is_a?(Array)
172
+ raise ConfigError, "Invalid value for :array" unless v.is_a?(Array)
157
173
  v.dup
158
174
  else
159
175
  unless type.respond_to?(:load)
160
176
  raise ArgumentError, "Unknown type #{type.to_s.dump}"
161
177
  end
162
- type.load(v)
178
+ begin
179
+ type.load(v)
180
+ rescue => e
181
+ raise ConfigError, e
182
+ end
163
183
  end
164
184
 
165
185
  elsif options.has_key?(:default)
166
186
  value = options[:default]
167
187
 
168
188
  else
169
- raise "Required field #{key.to_s.dump} is not set"
189
+ raise ConfigError, "Required field #{key.to_s.dump} is not set"
170
190
  end
171
191
 
172
192
  return value