embulk 0.1.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.
- checksums.yaml +15 -0
- data/.gitignore +13 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +33 -0
- data/README.md +117 -0
- data/Rakefile +58 -0
- data/bin/embulk +63 -0
- data/build.gradle +149 -0
- data/embulk-cli/build.gradle +6 -0
- data/embulk-cli/pom.xml +94 -0
- data/embulk-cli/src/main/java/org/embulk/cli/Main.java +15 -0
- data/embulk-core/build.gradle +6 -0
- data/embulk-core/pom.xml +143 -0
- data/embulk-core/src/main/java/org/embulk/EmbulkService.java +39 -0
- data/embulk-core/src/main/java/org/embulk/command/Runner.java +199 -0
- data/embulk-core/src/main/java/org/embulk/command/TablePrinter.java +119 -0
- data/embulk-core/src/main/java/org/embulk/config/CommitReport.java +26 -0
- data/embulk-core/src/main/java/org/embulk/config/Config.java +15 -0
- data/embulk-core/src/main/java/org/embulk/config/ConfigDefault.java +15 -0
- data/embulk-core/src/main/java/org/embulk/config/ConfigException.java +20 -0
- data/embulk-core/src/main/java/org/embulk/config/ConfigLoader.java +83 -0
- data/embulk-core/src/main/java/org/embulk/config/ConfigSource.java +28 -0
- data/embulk-core/src/main/java/org/embulk/config/DataSource.java +35 -0
- data/embulk-core/src/main/java/org/embulk/config/DataSourceImpl.java +208 -0
- data/embulk-core/src/main/java/org/embulk/config/DataSourceSerDe.java +80 -0
- data/embulk-core/src/main/java/org/embulk/config/GenericTypeReference.java +20 -0
- data/embulk-core/src/main/java/org/embulk/config/ModelManager.java +125 -0
- data/embulk-core/src/main/java/org/embulk/config/NextConfig.java +26 -0
- data/embulk-core/src/main/java/org/embulk/config/Task.java +10 -0
- data/embulk-core/src/main/java/org/embulk/config/TaskInvocationHandler.java +180 -0
- data/embulk-core/src/main/java/org/embulk/config/TaskSerDe.java +343 -0
- data/embulk-core/src/main/java/org/embulk/config/TaskSource.java +28 -0
- data/embulk-core/src/main/java/org/embulk/config/TaskValidationException.java +37 -0
- data/embulk-core/src/main/java/org/embulk/config/TaskValidator.java +24 -0
- data/embulk-core/src/main/java/org/embulk/exec/ExecModule.java +45 -0
- data/embulk-core/src/main/java/org/embulk/exec/ExecuteInterruptedException.java +10 -0
- data/embulk-core/src/main/java/org/embulk/exec/ExecuteResult.java +19 -0
- data/embulk-core/src/main/java/org/embulk/exec/ExtensionServiceLoaderModule.java +43 -0
- data/embulk-core/src/main/java/org/embulk/exec/ForSystemConfig.java +16 -0
- data/embulk-core/src/main/java/org/embulk/exec/GuessExecutor.java +307 -0
- data/embulk-core/src/main/java/org/embulk/exec/LocalExecutor.java +274 -0
- data/embulk-core/src/main/java/org/embulk/exec/LoggerProvider.java +30 -0
- data/embulk-core/src/main/java/org/embulk/exec/NoSampleException.java +10 -0
- data/embulk-core/src/main/java/org/embulk/exec/PooledBufferAllocator.java +58 -0
- data/embulk-core/src/main/java/org/embulk/exec/PreviewExecutor.java +138 -0
- data/embulk-core/src/main/java/org/embulk/exec/PreviewResult.java +27 -0
- data/embulk-core/src/main/java/org/embulk/exec/PreviewedNoticeError.java +17 -0
- data/embulk-core/src/main/java/org/embulk/exec/SamplingParserPlugin.java +116 -0
- data/embulk-core/src/main/java/org/embulk/exec/SystemConfigModule.java +24 -0
- data/embulk-core/src/main/java/org/embulk/jruby/JRubyPluginSource.java +69 -0
- data/embulk-core/src/main/java/org/embulk/jruby/JRubyScriptingModule.java +100 -0
- data/embulk-core/src/main/java/org/embulk/plugin/BuiltinPluginSourceModule.java +17 -0
- data/embulk-core/src/main/java/org/embulk/plugin/InjectedPluginSource.java +92 -0
- data/embulk-core/src/main/java/org/embulk/plugin/PluginManager.java +34 -0
- data/embulk-core/src/main/java/org/embulk/plugin/PluginSource.java +6 -0
- data/embulk-core/src/main/java/org/embulk/plugin/PluginSourceNotMatchException.java +19 -0
- data/embulk-core/src/main/java/org/embulk/plugin/PluginType.java +47 -0
- data/embulk-core/src/main/java/org/embulk/plugin/SetThreadContextClassLoader.java +19 -0
- data/embulk-core/src/main/java/org/embulk/spi/Buffer.java +113 -0
- data/embulk-core/src/main/java/org/embulk/spi/BufferAllocator.java +8 -0
- data/embulk-core/src/main/java/org/embulk/spi/Column.java +92 -0
- data/embulk-core/src/main/java/org/embulk/spi/ColumnConfig.java +79 -0
- data/embulk-core/src/main/java/org/embulk/spi/DecoderPlugin.java +16 -0
- data/embulk-core/src/main/java/org/embulk/spi/EncoderPlugin.java +16 -0
- data/embulk-core/src/main/java/org/embulk/spi/Exec.java +76 -0
- data/embulk-core/src/main/java/org/embulk/spi/ExecAction.java +6 -0
- data/embulk-core/src/main/java/org/embulk/spi/ExecSession.java +105 -0
- data/embulk-core/src/main/java/org/embulk/spi/Extension.java +42 -0
- data/embulk-core/src/main/java/org/embulk/spi/FileInput.java +11 -0
- data/embulk-core/src/main/java/org/embulk/spi/FileInputPlugin.java +19 -0
- data/embulk-core/src/main/java/org/embulk/spi/FileInputRunner.java +113 -0
- data/embulk-core/src/main/java/org/embulk/spi/FileOutput.java +13 -0
- data/embulk-core/src/main/java/org/embulk/spi/FileOutputPlugin.java +20 -0
- data/embulk-core/src/main/java/org/embulk/spi/FileOutputRunner.java +167 -0
- data/embulk-core/src/main/java/org/embulk/spi/FormatterPlugin.java +18 -0
- data/embulk-core/src/main/java/org/embulk/spi/GuessPlugin.java +9 -0
- data/embulk-core/src/main/java/org/embulk/spi/InputPlugin.java +20 -0
- data/embulk-core/src/main/java/org/embulk/spi/OutputPlugin.java +21 -0
- data/embulk-core/src/main/java/org/embulk/spi/Page.java +45 -0
- data/embulk-core/src/main/java/org/embulk/spi/PageBuilder.java +327 -0
- data/embulk-core/src/main/java/org/embulk/spi/PageFormat.java +47 -0
- data/embulk-core/src/main/java/org/embulk/spi/PageOutput.java +11 -0
- data/embulk-core/src/main/java/org/embulk/spi/PageReader.java +227 -0
- data/embulk-core/src/main/java/org/embulk/spi/ParserPlugin.java +17 -0
- data/embulk-core/src/main/java/org/embulk/spi/Schema.java +101 -0
- data/embulk-core/src/main/java/org/embulk/spi/SchemaConfig.java +52 -0
- data/embulk-core/src/main/java/org/embulk/spi/SchemaVisitor.java +14 -0
- data/embulk-core/src/main/java/org/embulk/spi/Transactional.java +10 -0
- data/embulk-core/src/main/java/org/embulk/spi/TransactionalFileInput.java +17 -0
- data/embulk-core/src/main/java/org/embulk/spi/TransactionalFileOutput.java +19 -0
- data/embulk-core/src/main/java/org/embulk/spi/TransactionalPageOutput.java +17 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/DateTimeZoneSerDe.java +57 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/JRubyTimeParserHelper.java +8 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/JRubyTimeParserHelperFactory.java +6 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/Timestamp.java +159 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/TimestampFormat.java +98 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/TimestampFormatter.java +55 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/TimestampParseException.java +6 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/TimestampParser.java +60 -0
- data/embulk-core/src/main/java/org/embulk/spi/time/TimestampSerDe.java +50 -0
- data/embulk-core/src/main/java/org/embulk/spi/type/AbstractType.java +55 -0
- data/embulk-core/src/main/java/org/embulk/spi/type/BooleanType.java +12 -0
- data/embulk-core/src/main/java/org/embulk/spi/type/DoubleType.java +12 -0
- data/embulk-core/src/main/java/org/embulk/spi/type/LongType.java +12 -0
- data/embulk-core/src/main/java/org/embulk/spi/type/StringType.java +12 -0
- data/embulk-core/src/main/java/org/embulk/spi/type/TimestampType.java +39 -0
- data/embulk-core/src/main/java/org/embulk/spi/type/Type.java +15 -0
- data/embulk-core/src/main/java/org/embulk/spi/type/TypeDeserializer.java +47 -0
- data/embulk-core/src/main/java/org/embulk/spi/type/Types.java +14 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/CharsetSerDe.java +55 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/Decoders.java +81 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/Encoders.java +81 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/FileInputInputStream.java +110 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/FileOutputOutputStream.java +94 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/InputStreamFileInput.java +111 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/Inputs.java +74 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/LineDecoder.java +118 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/LineEncoder.java +109 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/ListFileInput.java +52 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/Newline.java +38 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/PagePrinter.java +102 -0
- data/embulk-core/src/main/java/org/embulk/spi/util/Pages.java +139 -0
- data/embulk-core/src/test/java/org/embulk/EmbulkTestRuntime.java +110 -0
- data/embulk-core/src/test/java/org/embulk/GuiceBinder.java +72 -0
- data/embulk-core/src/test/java/org/embulk/RandomManager.java +53 -0
- data/embulk-core/src/test/java/org/embulk/TestPluginSourceModule.java +23 -0
- data/embulk-core/src/test/java/org/embulk/TestUtilityModule.java +17 -0
- data/embulk-core/src/test/java/org/embulk/config/TestConfigSource.java +114 -0
- data/embulk-core/src/test/java/org/embulk/config/TestTaskSource.java +70 -0
- data/embulk-core/src/test/java/org/embulk/plugin/MockPluginSource.java +57 -0
- data/embulk-core/src/test/java/org/embulk/plugin/TestPluginType.java +18 -0
- data/embulk-core/src/test/java/org/embulk/spi/MockFileOutput.java +63 -0
- data/embulk-core/src/test/java/org/embulk/spi/MockFormatterPlugin.java +101 -0
- data/embulk-core/src/test/java/org/embulk/spi/MockParserPlugin.java +73 -0
- data/embulk-core/src/test/java/org/embulk/spi/PageTestUtils.java +78 -0
- data/embulk-core/src/test/java/org/embulk/spi/TestFileInputInputStream.java +67 -0
- data/embulk-core/src/test/java/org/embulk/spi/TestFileInputRunner.java +180 -0
- data/embulk-core/src/test/java/org/embulk/spi/TestFileOutputRunner.java +192 -0
- data/embulk-core/src/test/java/org/embulk/spi/TestInputStreamFileInput.java +188 -0
- data/embulk-core/src/test/java/org/embulk/spi/TestPageBuilderReader.java +301 -0
- data/embulk-core/src/test/java/org/embulk/spi/time/TestTimestamp.java +116 -0
- data/embulk-core/src/test/java/org/embulk/spi/time/TestTimestampFormatterParser.java +52 -0
- data/embulk-core/src/test/java/org/embulk/spi/type/TestTypeSerDe.java +45 -0
- data/embulk-core/src/test/java/org/embulk/spi/util/TestLineDecoder.java +132 -0
- data/embulk-core/src/test/java/org/embulk/spi/util/TestLineEncoder.java +123 -0
- data/embulk-standards/build.gradle +6 -0
- data/embulk-standards/pom.xml +68 -0
- data/embulk-standards/src/main/java/org/embulk/standards/CsvFormatterPlugin.java +158 -0
- data/embulk-standards/src/main/java/org/embulk/standards/CsvParserPlugin.java +233 -0
- data/embulk-standards/src/main/java/org/embulk/standards/CsvTokenizer.java +355 -0
- data/embulk-standards/src/main/java/org/embulk/standards/GzipFileDecoderPlugin.java +55 -0
- data/embulk-standards/src/main/java/org/embulk/standards/GzipFileEncoderPlugin.java +39 -0
- data/embulk-standards/src/main/java/org/embulk/standards/LocalFileInputPlugin.java +138 -0
- data/embulk-standards/src/main/java/org/embulk/standards/LocalFileOutputPlugin.java +128 -0
- data/embulk-standards/src/main/java/org/embulk/standards/NullOutputPlugin.java +46 -0
- data/embulk-standards/src/main/java/org/embulk/standards/S3FileInputPlugin.java +238 -0
- data/embulk-standards/src/main/java/org/embulk/standards/StandardPluginExtension.java +16 -0
- data/embulk-standards/src/main/java/org/embulk/standards/StandardPluginModule.java +44 -0
- data/embulk-standards/src/main/java/org/embulk/standards/StdoutOutputPlugin.java +71 -0
- data/embulk-standards/src/main/resources/META-INF/services/org.embulk.spi.Extension +1 -0
- data/embulk-standards/src/test/java/org/embulk/standards/TestCsvParserPlugin.java +69 -0
- data/embulk-standards/src/test/java/org/embulk/standards/TestCsvTokenizer.java +291 -0
- data/embulk-standards/src/test/java/org/embulk/standards/TestS3FileInputPlugin.java +43 -0
- data/embulk.gemspec +27 -0
- data/examples/config.yml +34 -0
- data/examples/csv/sample.csv.gz +0 -0
- data/gradle/wrapper/gradle-wrapper.jar +0 -0
- data/gradle/wrapper/gradle-wrapper.properties +6 -0
- data/gradlew +164 -0
- data/gradlew.bat +90 -0
- data/lib/embulk.rb +16 -0
- data/lib/embulk/buffer.rb +17 -0
- data/lib/embulk/column.rb +47 -0
- data/lib/embulk/command/embulk.rb +39 -0
- data/lib/embulk/command/embulk_example.rb +32 -0
- data/lib/embulk/command/embulk_generate_bin.rb +62 -0
- data/lib/embulk/command/embulk_run.rb +243 -0
- data/lib/embulk/data/bundle/.bundle/config +3 -0
- data/lib/embulk/data/bundle/Gemfile +31 -0
- data/lib/embulk/data/bundle/Gemfile.lock +8 -0
- data/lib/embulk/data/bundle/embulk/input_example.rb +40 -0
- data/lib/embulk/data/bundle/embulk/output_example.rb +51 -0
- data/lib/embulk/data_source.rb +66 -0
- data/lib/embulk/error.rb +5 -0
- data/lib/embulk/guess_charset.rb +26 -0
- data/lib/embulk/guess_csv.rb +195 -0
- data/lib/embulk/guess_gzip.rb +18 -0
- data/lib/embulk/guess_newline.rb +20 -0
- data/lib/embulk/guess_plugin.rb +113 -0
- data/lib/embulk/input_plugin.rb +53 -0
- data/lib/embulk/java/bootstrap.rb +12 -0
- data/lib/embulk/java/imports.rb +26 -0
- data/lib/embulk/java/time_helper.rb +77 -0
- data/lib/embulk/output_plugin.rb +104 -0
- data/lib/embulk/page.rb +28 -0
- data/lib/embulk/page_builder.rb +22 -0
- data/lib/embulk/plugin.rb +152 -0
- data/lib/embulk/plugin_registry.rb +70 -0
- data/lib/embulk/schema.rb +85 -0
- data/lib/embulk/time_format_guess.rb +331 -0
- data/lib/embulk/version.rb +3 -0
- data/pom.xml +533 -0
- data/settings.gradle +5 -0
- metadata +370 -0
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
package org.embulk.config;
|
|
2
|
+
|
|
3
|
+
import java.lang.reflect.Proxy;
|
|
4
|
+
import java.lang.reflect.Method;
|
|
5
|
+
import java.lang.reflect.Type;
|
|
6
|
+
import java.io.IOException;
|
|
7
|
+
import java.util.List;
|
|
8
|
+
import java.util.Map;
|
|
9
|
+
import java.util.HashMap;
|
|
10
|
+
import java.util.concurrent.ConcurrentHashMap;
|
|
11
|
+
import com.google.common.base.Optional;
|
|
12
|
+
import com.google.common.collect.ImmutableList;
|
|
13
|
+
import com.google.common.collect.ImmutableSet;
|
|
14
|
+
import com.google.common.collect.ImmutableMap;
|
|
15
|
+
import com.fasterxml.jackson.core.JsonGenerator;
|
|
16
|
+
import com.fasterxml.jackson.core.JsonParser;
|
|
17
|
+
import com.fasterxml.jackson.core.JsonToken;
|
|
18
|
+
import com.fasterxml.jackson.core.Version;
|
|
19
|
+
import com.fasterxml.jackson.databind.Module;
|
|
20
|
+
import com.fasterxml.jackson.databind.module.SimpleModule;
|
|
21
|
+
import com.fasterxml.jackson.databind.deser.Deserializers;
|
|
22
|
+
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
23
|
+
import com.fasterxml.jackson.databind.JavaType;
|
|
24
|
+
import com.fasterxml.jackson.databind.BeanDescription;
|
|
25
|
+
import com.fasterxml.jackson.databind.JsonSerializer;
|
|
26
|
+
import com.fasterxml.jackson.databind.JsonDeserializer;
|
|
27
|
+
import com.fasterxml.jackson.databind.SerializerProvider;
|
|
28
|
+
import com.fasterxml.jackson.databind.DeserializationContext;
|
|
29
|
+
import com.fasterxml.jackson.databind.DeserializationConfig;
|
|
30
|
+
import com.fasterxml.jackson.databind.JsonMappingException;
|
|
31
|
+
import com.fasterxml.jackson.annotation.JacksonInject;
|
|
32
|
+
|
|
33
|
+
class TaskSerDe
|
|
34
|
+
{
|
|
35
|
+
public static class TaskSerializer
|
|
36
|
+
extends JsonSerializer<Task>
|
|
37
|
+
{
|
|
38
|
+
private final ObjectMapper nestedObjectMapper;
|
|
39
|
+
|
|
40
|
+
public TaskSerializer(ObjectMapper nestedObjectMapper)
|
|
41
|
+
{
|
|
42
|
+
this.nestedObjectMapper = nestedObjectMapper;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@Override
|
|
46
|
+
public void serialize(Task value, JsonGenerator jgen, SerializerProvider provider)
|
|
47
|
+
throws IOException
|
|
48
|
+
{
|
|
49
|
+
if (value instanceof Proxy) {
|
|
50
|
+
Object handler = Proxy.getInvocationHandler(value);
|
|
51
|
+
if (handler instanceof TaskInvocationHandler) {
|
|
52
|
+
TaskInvocationHandler h = (TaskInvocationHandler) handler;
|
|
53
|
+
Map<String, Object> objects = h.getObjects();
|
|
54
|
+
jgen.writeStartObject();
|
|
55
|
+
for (Map.Entry<String, Object> pair : objects.entrySet()) {
|
|
56
|
+
if (h.getInjectedFields().contains(pair.getKey())) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
jgen.writeFieldName(pair.getKey());
|
|
60
|
+
nestedObjectMapper.writeValue(jgen, pair.getValue());
|
|
61
|
+
}
|
|
62
|
+
jgen.writeEndObject();
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// TODO exception class & message
|
|
67
|
+
throw new UnsupportedOperationException("Serializing Task is not supported");
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
public static class TaskDeserializer <T>
|
|
72
|
+
extends JsonDeserializer<T>
|
|
73
|
+
{
|
|
74
|
+
private final ObjectMapper nestedObjectMapper;
|
|
75
|
+
private final ModelManager model;
|
|
76
|
+
private final Class<?> iface;
|
|
77
|
+
private final Map<String, FieldEntry> mappings;
|
|
78
|
+
private final List<InjectEntry> injects;
|
|
79
|
+
|
|
80
|
+
public TaskDeserializer(ObjectMapper nestedObjectMapper, ModelManager model, Class<T> iface)
|
|
81
|
+
{
|
|
82
|
+
this.nestedObjectMapper = nestedObjectMapper;
|
|
83
|
+
this.model = model;
|
|
84
|
+
this.iface = iface;
|
|
85
|
+
this.mappings = getterMappings(iface);
|
|
86
|
+
this.injects = injectEntries(iface);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
protected Map<String, FieldEntry> getterMappings(Class<?> iface)
|
|
90
|
+
{
|
|
91
|
+
ImmutableMap.Builder<String, FieldEntry> builder = ImmutableMap.builder();
|
|
92
|
+
for (Map.Entry<String, Method> getter : TaskInvocationHandler.fieldGetters(iface).entrySet()) {
|
|
93
|
+
Method getterMethod = getter.getValue();
|
|
94
|
+
String fieldName = getter.getKey();
|
|
95
|
+
|
|
96
|
+
if (getterMethod.getAnnotation(JacksonInject.class) != null) {
|
|
97
|
+
// InjectEntry
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
Type fieldType = getterMethod.getGenericReturnType();
|
|
102
|
+
|
|
103
|
+
Optional<String> jsonKey = getJsonKey(getterMethod, fieldName);
|
|
104
|
+
if (!jsonKey.isPresent()) {
|
|
105
|
+
// skip this field
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
Optional<String> defaultJsonString = getDefaultJsonString(getterMethod);
|
|
109
|
+
builder.put(jsonKey.get(), new FieldEntry(fieldName, fieldType, defaultJsonString));
|
|
110
|
+
}
|
|
111
|
+
return builder.build();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
protected List<InjectEntry> injectEntries(Class<?> iface)
|
|
115
|
+
{
|
|
116
|
+
ImmutableList.Builder<InjectEntry> builder = ImmutableList.builder();
|
|
117
|
+
for (Map.Entry<String, Method> getter : TaskInvocationHandler.fieldGetters(iface).entrySet()) {
|
|
118
|
+
Method getterMethod = getter.getValue();
|
|
119
|
+
String fieldName = getter.getKey();
|
|
120
|
+
JacksonInject inject = getterMethod.getAnnotation(JacksonInject.class);
|
|
121
|
+
if (inject != null) {
|
|
122
|
+
// InjectEntry
|
|
123
|
+
builder.add(new InjectEntry(fieldName, getterMethod.getReturnType()));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return builder.build();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
protected Optional<String> getJsonKey(Method getterMethod, String fieldName)
|
|
130
|
+
{
|
|
131
|
+
return Optional.of(fieldName);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
protected Optional<String> getDefaultJsonString(Method getterMethod)
|
|
135
|
+
{
|
|
136
|
+
return Optional.absent();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
@Override
|
|
140
|
+
public T deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
|
|
141
|
+
{
|
|
142
|
+
Map<String, Object> objects = new ConcurrentHashMap<String, Object>();
|
|
143
|
+
HashMap<String, FieldEntry> unusedMappings = new HashMap<>(mappings);
|
|
144
|
+
|
|
145
|
+
JsonToken current;
|
|
146
|
+
current = jp.getCurrentToken();
|
|
147
|
+
if (current == JsonToken.START_OBJECT) {
|
|
148
|
+
current = jp.nextToken();
|
|
149
|
+
}
|
|
150
|
+
for (; current != JsonToken.END_OBJECT; current = jp.nextToken()) {
|
|
151
|
+
String key = jp.getCurrentName();
|
|
152
|
+
current = jp.nextToken();
|
|
153
|
+
FieldEntry field = mappings.get(key);
|
|
154
|
+
if (field == null) {
|
|
155
|
+
jp.skipChildren();
|
|
156
|
+
} else {
|
|
157
|
+
Object value = nestedObjectMapper.readValue(jp, new GenericTypeReference(field.getType()));
|
|
158
|
+
if (value == null) {
|
|
159
|
+
throw new JsonMappingException("Setting null to a @Config field is not allowed. Configuration object must be Optional<T> (com.google.common.base.Optional)");
|
|
160
|
+
}
|
|
161
|
+
objects.put(field.getName(), value);
|
|
162
|
+
unusedMappings.remove(key);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// set default values
|
|
167
|
+
for (Map.Entry<String, FieldEntry> unused : unusedMappings.entrySet()) {
|
|
168
|
+
FieldEntry field = unused.getValue();
|
|
169
|
+
if (field.getDefaultJsonString().isPresent()) {
|
|
170
|
+
Object value = nestedObjectMapper.readValue(field.getDefaultJsonString().get(), new GenericTypeReference(field.getType()));
|
|
171
|
+
if (value == null) {
|
|
172
|
+
throw new JsonMappingException("Setting null to a @Config field is not allowed. Configuration object must be Optional<T> (com.google.common.base.Optional)");
|
|
173
|
+
}
|
|
174
|
+
objects.put(field.getName(), value);
|
|
175
|
+
} else {
|
|
176
|
+
// required field
|
|
177
|
+
throw new JsonMappingException("Field '"+unused.getKey()+"' is required but not set", jp.getCurrentLocation());
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// inject
|
|
182
|
+
ImmutableSet.Builder<String> injectedFields = ImmutableSet.builder();
|
|
183
|
+
for (InjectEntry inject : injects) {
|
|
184
|
+
objects.put(inject.getName(), model.getInjectedInstance(inject.getType()));
|
|
185
|
+
injectedFields.add(inject.getName());
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return (T) Proxy.newProxyInstance(
|
|
189
|
+
iface.getClassLoader(), new Class<?>[] { iface },
|
|
190
|
+
new TaskInvocationHandler(model, iface, objects, injectedFields.build()));
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
private static class FieldEntry
|
|
194
|
+
{
|
|
195
|
+
private final String name;
|
|
196
|
+
private final Type type;
|
|
197
|
+
private final Optional<String> defaultJsonString;
|
|
198
|
+
|
|
199
|
+
public FieldEntry(String name, Type type, Optional<String> defaultJsonString)
|
|
200
|
+
{
|
|
201
|
+
this.name = name;
|
|
202
|
+
this.type = type;
|
|
203
|
+
this.defaultJsonString = defaultJsonString;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
public String getName()
|
|
207
|
+
{
|
|
208
|
+
return name;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
public Type getType()
|
|
212
|
+
{
|
|
213
|
+
return type;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
public Optional<String> getDefaultJsonString()
|
|
217
|
+
{
|
|
218
|
+
return defaultJsonString;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
private static class InjectEntry
|
|
223
|
+
{
|
|
224
|
+
private final String name;
|
|
225
|
+
private Class<?> type;
|
|
226
|
+
|
|
227
|
+
public InjectEntry(String name, Class<?> type)
|
|
228
|
+
{
|
|
229
|
+
this.name = name;
|
|
230
|
+
this.type = type;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
public String getName()
|
|
234
|
+
{
|
|
235
|
+
return name;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
public Class<?> getType()
|
|
239
|
+
{
|
|
240
|
+
return type;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
public static class TaskSerializerModule
|
|
246
|
+
extends SimpleModule
|
|
247
|
+
{
|
|
248
|
+
public TaskSerializerModule(ObjectMapper nestedObjectMapper)
|
|
249
|
+
{
|
|
250
|
+
super();
|
|
251
|
+
addSerializer(Task.class, new TaskSerializer(nestedObjectMapper));
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
public static class ConfigTaskDeserializer <T>
|
|
256
|
+
extends TaskDeserializer<T>
|
|
257
|
+
{
|
|
258
|
+
public ConfigTaskDeserializer(ObjectMapper nestedObjectMapper, ModelManager model, Class<T> iface)
|
|
259
|
+
{
|
|
260
|
+
super(nestedObjectMapper, model, iface);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
@Override
|
|
264
|
+
protected Optional<String> getJsonKey(Method getterMethod, String fieldName)
|
|
265
|
+
{
|
|
266
|
+
Config a = getterMethod.getAnnotation(Config.class);
|
|
267
|
+
if (a != null) {
|
|
268
|
+
return Optional.of(a.value());
|
|
269
|
+
} else {
|
|
270
|
+
return Optional.absent(); // skip this field
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
@Override
|
|
275
|
+
public Optional<String> getDefaultJsonString(Method getterMethod)
|
|
276
|
+
{
|
|
277
|
+
ConfigDefault a = getterMethod.getAnnotation(ConfigDefault.class);
|
|
278
|
+
if (a != null && !a.value().isEmpty()) {
|
|
279
|
+
return Optional.of(a.value());
|
|
280
|
+
}
|
|
281
|
+
return super.getDefaultJsonString(getterMethod);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
public static class TaskDeserializerModule
|
|
286
|
+
extends Module // can't use just SimpleModule, due to generic types
|
|
287
|
+
{
|
|
288
|
+
protected final ObjectMapper nestedObjectMapper;
|
|
289
|
+
protected final ModelManager model;
|
|
290
|
+
|
|
291
|
+
public TaskDeserializerModule(ObjectMapper nestedObjectMapper, ModelManager model)
|
|
292
|
+
{
|
|
293
|
+
this.nestedObjectMapper = nestedObjectMapper;
|
|
294
|
+
this.model = model;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
@Override
|
|
298
|
+
public String getModuleName() { return "embulk.config.TaskSerDe"; }
|
|
299
|
+
|
|
300
|
+
@Override
|
|
301
|
+
public Version version() { return Version.unknownVersion(); }
|
|
302
|
+
|
|
303
|
+
@Override
|
|
304
|
+
public void setupModule(SetupContext context)
|
|
305
|
+
{
|
|
306
|
+
context.addDeserializers(new Deserializers.Base() {
|
|
307
|
+
@Override
|
|
308
|
+
public JsonDeserializer<?> findBeanDeserializer(JavaType type, DeserializationConfig config,
|
|
309
|
+
BeanDescription beanDesc) throws JsonMappingException
|
|
310
|
+
{
|
|
311
|
+
Class<?> raw = type.getRawClass();
|
|
312
|
+
if (Task.class.isAssignableFrom(raw)) {
|
|
313
|
+
return newTaskDeserializer(raw);
|
|
314
|
+
}
|
|
315
|
+
return super.findBeanDeserializer(type, config, beanDesc);
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
protected JsonDeserializer<?> newTaskDeserializer(Class<?> raw)
|
|
321
|
+
{
|
|
322
|
+
return new TaskDeserializer(nestedObjectMapper, model, raw);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
public static class ConfigTaskDeserializerModule
|
|
327
|
+
extends TaskDeserializerModule
|
|
328
|
+
{
|
|
329
|
+
public ConfigTaskDeserializerModule(ObjectMapper nestedObjectMapper, ModelManager model)
|
|
330
|
+
{
|
|
331
|
+
super(nestedObjectMapper, model);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
@Override
|
|
335
|
+
public String getModuleName() { return "embulk.config.ConfigTaskSerDe"; }
|
|
336
|
+
|
|
337
|
+
@Override
|
|
338
|
+
protected JsonDeserializer<?> newTaskDeserializer(Class<?> raw)
|
|
339
|
+
{
|
|
340
|
+
return new ConfigTaskDeserializer(nestedObjectMapper, model, raw);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
package org.embulk.config;
|
|
2
|
+
|
|
3
|
+
public interface TaskSource
|
|
4
|
+
extends DataSource
|
|
5
|
+
{
|
|
6
|
+
public <T extends Task> T loadTask(Class<T> taskType);
|
|
7
|
+
|
|
8
|
+
@Override
|
|
9
|
+
public TaskSource getNested(String attrName);
|
|
10
|
+
|
|
11
|
+
@Override
|
|
12
|
+
public TaskSource getNestedOrSetEmpty(String attrName);
|
|
13
|
+
|
|
14
|
+
@Override
|
|
15
|
+
public TaskSource set(String attrName, Object v);
|
|
16
|
+
|
|
17
|
+
@Override
|
|
18
|
+
public TaskSource setNested(String attrName, DataSource v);
|
|
19
|
+
|
|
20
|
+
@Override
|
|
21
|
+
public TaskSource setAll(DataSource other);
|
|
22
|
+
|
|
23
|
+
@Override
|
|
24
|
+
public TaskSource deepCopy();
|
|
25
|
+
|
|
26
|
+
@Override
|
|
27
|
+
public TaskSource merge(DataSource other);
|
|
28
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
package org.embulk.config;
|
|
2
|
+
|
|
3
|
+
import java.util.Set;
|
|
4
|
+
import javax.validation.ConstraintViolation;
|
|
5
|
+
|
|
6
|
+
public class TaskValidationException
|
|
7
|
+
extends RuntimeException
|
|
8
|
+
{
|
|
9
|
+
@SuppressWarnings("unchecked")
|
|
10
|
+
private final Set violations;
|
|
11
|
+
|
|
12
|
+
public <T> TaskValidationException(Set<ConstraintViolation<T>> violations)
|
|
13
|
+
{
|
|
14
|
+
super(formatMessage(violations));
|
|
15
|
+
this.violations = violations;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public Set<ConstraintViolation<?>> getViolations()
|
|
19
|
+
{
|
|
20
|
+
return violations;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
private static <T> String formatMessage(Set<ConstraintViolation<T>> violations)
|
|
24
|
+
{
|
|
25
|
+
StringBuilder sb = new StringBuilder();
|
|
26
|
+
sb.append("Configuration task validation failed.");
|
|
27
|
+
for(ConstraintViolation<T> violation : violations) {
|
|
28
|
+
sb.append(" ");
|
|
29
|
+
sb.append(violation.getPropertyPath());
|
|
30
|
+
sb.append(" ");
|
|
31
|
+
sb.append(violation.getMessage());
|
|
32
|
+
sb.append(" but got ");
|
|
33
|
+
sb.append(violation.getInvalidValue());
|
|
34
|
+
}
|
|
35
|
+
return sb.toString();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
package org.embulk.config;
|
|
2
|
+
|
|
3
|
+
import java.util.Set;
|
|
4
|
+
import javax.validation.Validator;
|
|
5
|
+
import javax.validation.ConstraintViolation;
|
|
6
|
+
|
|
7
|
+
public class TaskValidator
|
|
8
|
+
{
|
|
9
|
+
private final Validator validator;
|
|
10
|
+
|
|
11
|
+
public TaskValidator(Validator validator)
|
|
12
|
+
{
|
|
13
|
+
this.validator = validator;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
public <T> void validateModel(T model) throws TaskValidationException
|
|
17
|
+
{
|
|
18
|
+
Set<ConstraintViolation<T>> violations = validator.validate(model);
|
|
19
|
+
if (!violations.isEmpty()) {
|
|
20
|
+
throw new TaskValidationException(violations);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
package org.embulk.exec;
|
|
2
|
+
|
|
3
|
+
import org.slf4j.ILoggerFactory;
|
|
4
|
+
import com.google.common.base.Preconditions;
|
|
5
|
+
import com.google.inject.Module;
|
|
6
|
+
import com.google.inject.name.Names;
|
|
7
|
+
import com.google.inject.Binder;
|
|
8
|
+
import com.google.inject.Scopes;
|
|
9
|
+
import com.fasterxml.jackson.module.guice.ObjectMapperModule;
|
|
10
|
+
import com.fasterxml.jackson.datatype.guava.GuavaModule;
|
|
11
|
+
import com.fasterxml.jackson.datatype.joda.JodaModule;
|
|
12
|
+
import org.embulk.config.ModelManager;
|
|
13
|
+
import org.embulk.spi.time.DateTimeZoneSerDe;
|
|
14
|
+
import org.embulk.spi.time.TimestampSerDe;
|
|
15
|
+
import org.embulk.spi.ParserPlugin;
|
|
16
|
+
import org.embulk.spi.BufferAllocator;
|
|
17
|
+
import org.embulk.spi.util.CharsetSerDe;
|
|
18
|
+
import static org.embulk.plugin.InjectedPluginSource.registerPluginTo;
|
|
19
|
+
|
|
20
|
+
public class ExecModule
|
|
21
|
+
implements Module
|
|
22
|
+
{
|
|
23
|
+
@Override
|
|
24
|
+
public void configure(Binder binder)
|
|
25
|
+
{
|
|
26
|
+
Preconditions.checkNotNull(binder, "binder is null.");
|
|
27
|
+
|
|
28
|
+
binder.bind(ILoggerFactory.class).toProvider(LoggerProvider.class);
|
|
29
|
+
binder.bind(ModelManager.class).in(Scopes.SINGLETON);
|
|
30
|
+
binder.bind(BufferAllocator.class).to(PooledBufferAllocator.class).in(Scopes.SINGLETON);
|
|
31
|
+
|
|
32
|
+
// GuessExecutor
|
|
33
|
+
registerPluginTo(binder, ParserPlugin.class, "system_guess", GuessExecutor.GuessParserPlugin.class);
|
|
34
|
+
registerPluginTo(binder, ParserPlugin.class, "system_sampling", SamplingParserPlugin.class);
|
|
35
|
+
|
|
36
|
+
// serde
|
|
37
|
+
ObjectMapperModule mapper = new ObjectMapperModule();
|
|
38
|
+
DateTimeZoneSerDe.configure(mapper);
|
|
39
|
+
TimestampSerDe.configure(mapper);
|
|
40
|
+
CharsetSerDe.configure(mapper);
|
|
41
|
+
mapper.registerModule(new GuavaModule()); // jackson-datatype-guava
|
|
42
|
+
mapper.registerModule(new JodaModule()); // jackson-datatype-joda
|
|
43
|
+
mapper.configure(binder);
|
|
44
|
+
}
|
|
45
|
+
}
|