embulk-output-s3 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,108 +1,108 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <!DOCTYPE module PUBLIC
3
- "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
4
- "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
5
- <!--
6
- This is a subset of ./checkstyle.xml which allows some loose styles
7
- -->
8
- <module name="Checker">
9
- <module name="FileTabCharacter"/>
10
- <module name="NewlineAtEndOfFile">
11
- <property name="lineSeparator" value="lf"/>
12
- </module>
13
- <module name="RegexpMultiline">
14
- <property name="format" value="\r"/>
15
- <property name="message" value="Line contains carriage return"/>
16
- </module>
17
- <module name="RegexpMultiline">
18
- <property name="format" value=" \n"/>
19
- <property name="message" value="Line has trailing whitespace"/>
20
- </module>
21
- <module name="RegexpMultiline">
22
- <property name="format" value="\n\n\n"/>
23
- <property name="message" value="Multiple consecutive blank lines"/>
24
- </module>
25
- <module name="RegexpMultiline">
26
- <property name="format" value="\n\n\Z"/>
27
- <property name="message" value="Blank line before end of file"/>
28
- </module>
29
-
30
- <module name="TreeWalker">
31
- <module name="EmptyBlock">
32
- <property name="option" value="text"/>
33
- <property name="tokens" value="
34
- LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_IF,
35
- LITERAL_FOR, LITERAL_TRY, LITERAL_WHILE, INSTANCE_INIT, STATIC_INIT"/>
36
- </module>
37
- <module name="EmptyStatement"/>
38
- <module name="EmptyForInitializerPad"/>
39
- <module name="EmptyForIteratorPad">
40
- <property name="option" value="space"/>
41
- </module>
42
- <module name="MethodParamPad">
43
- <property name="allowLineBreaks" value="true"/>
44
- <property name="option" value="nospace"/>
45
- </module>
46
- <module name="ParenPad"/>
47
- <module name="TypecastParenPad"/>
48
- <module name="NeedBraces"/>
49
- <module name="LeftCurly">
50
- <property name="option" value="nl"/>
51
- <property name="tokens" value="CLASS_DEF, CTOR_DEF, INTERFACE_DEF, METHOD_DEF"/>
52
- </module>
53
- <module name="LeftCurly">
54
- <property name="option" value="eol"/>
55
- <property name="tokens" value="
56
- LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR,
57
- LITERAL_IF, LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE"/>
58
- </module>
59
- <module name="RightCurly">
60
- <property name="option" value="alone"/>
61
- </module>
62
- <module name="GenericWhitespace"/>
63
- <module name="WhitespaceAfter"/>
64
- <module name="NoWhitespaceBefore"/>
65
-
66
- <module name="UpperEll"/>
67
- <module name="DefaultComesLast"/>
68
- <module name="ArrayTypeStyle"/>
69
- <module name="MultipleVariableDeclarations"/>
70
- <module name="ModifierOrder"/>
71
- <module name="OneStatementPerLine"/>
72
- <module name="StringLiteralEquality"/>
73
- <module name="MutableException"/>
74
- <module name="EqualsHashCode"/>
75
- <module name="InnerAssignment"/>
76
- <module name="InterfaceIsType"/>
77
- <module name="HideUtilityClassConstructor"/>
78
-
79
- <module name="MemberName"/>
80
- <module name="LocalVariableName"/>
81
- <module name="LocalFinalVariableName"/>
82
- <module name="TypeName"/>
83
- <module name="PackageName"/>
84
- <module name="ParameterName"/>
85
- <module name="StaticVariableName"/>
86
- <module name="ClassTypeParameterName">
87
- <property name="format" value="^[A-Z][0-9]?$"/>
88
- </module>
89
- <module name="MethodTypeParameterName">
90
- <property name="format" value="^[A-Z][0-9]?$"/>
91
- </module>
92
-
93
- <module name="WhitespaceAround">
94
- <property name="allowEmptyConstructors" value="true"/>
95
- <property name="allowEmptyMethods" value="true"/>
96
- <property name="ignoreEnhancedForColon" value="false"/>
97
- <property name="tokens" value="
98
- ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN,
99
- BXOR, BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, EQUAL, GE, GT, LAND, LE,
100
- LITERAL_ASSERT, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE,
101
- LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF, LITERAL_RETURN,
102
- LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE,
103
- LOR, LT, MINUS, MINUS_ASSIGN, MOD, MOD_ASSIGN, NOT_EQUAL,
104
- PLUS, PLUS_ASSIGN, QUESTION, SL, SLIST, SL_ASSIGN, SR, SR_ASSIGN,
105
- STAR, STAR_ASSIGN, TYPE_EXTENSION_AND"/>
106
- </module>
107
- </module>
108
- </module>
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE module PUBLIC
3
+ "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
4
+ "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
5
+ <!--
6
+ This is a subset of ./checkstyle.xml which allows some loose styles
7
+ -->
8
+ <module name="Checker">
9
+ <module name="FileTabCharacter"/>
10
+ <module name="NewlineAtEndOfFile">
11
+ <property name="lineSeparator" value="lf"/>
12
+ </module>
13
+ <module name="RegexpMultiline">
14
+ <property name="format" value="\r"/>
15
+ <property name="message" value="Line contains carriage return"/>
16
+ </module>
17
+ <module name="RegexpMultiline">
18
+ <property name="format" value=" \n"/>
19
+ <property name="message" value="Line has trailing whitespace"/>
20
+ </module>
21
+ <module name="RegexpMultiline">
22
+ <property name="format" value="\n\n\n"/>
23
+ <property name="message" value="Multiple consecutive blank lines"/>
24
+ </module>
25
+ <module name="RegexpMultiline">
26
+ <property name="format" value="\n\n\Z"/>
27
+ <property name="message" value="Blank line before end of file"/>
28
+ </module>
29
+
30
+ <module name="TreeWalker">
31
+ <module name="EmptyBlock">
32
+ <property name="option" value="text"/>
33
+ <property name="tokens" value="
34
+ LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_IF,
35
+ LITERAL_FOR, LITERAL_TRY, LITERAL_WHILE, INSTANCE_INIT, STATIC_INIT"/>
36
+ </module>
37
+ <module name="EmptyStatement"/>
38
+ <module name="EmptyForInitializerPad"/>
39
+ <module name="EmptyForIteratorPad">
40
+ <property name="option" value="space"/>
41
+ </module>
42
+ <module name="MethodParamPad">
43
+ <property name="allowLineBreaks" value="true"/>
44
+ <property name="option" value="nospace"/>
45
+ </module>
46
+ <module name="ParenPad"/>
47
+ <module name="TypecastParenPad"/>
48
+ <module name="NeedBraces"/>
49
+ <module name="LeftCurly">
50
+ <property name="option" value="nl"/>
51
+ <property name="tokens" value="CLASS_DEF, CTOR_DEF, INTERFACE_DEF, METHOD_DEF"/>
52
+ </module>
53
+ <module name="LeftCurly">
54
+ <property name="option" value="eol"/>
55
+ <property name="tokens" value="
56
+ LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE, LITERAL_FINALLY, LITERAL_FOR,
57
+ LITERAL_IF, LITERAL_SWITCH, LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE"/>
58
+ </module>
59
+ <module name="RightCurly">
60
+ <property name="option" value="alone"/>
61
+ </module>
62
+ <module name="GenericWhitespace"/>
63
+ <module name="WhitespaceAfter"/>
64
+ <module name="NoWhitespaceBefore"/>
65
+
66
+ <module name="UpperEll"/>
67
+ <module name="DefaultComesLast"/>
68
+ <module name="ArrayTypeStyle"/>
69
+ <module name="MultipleVariableDeclarations"/>
70
+ <module name="ModifierOrder"/>
71
+ <module name="OneStatementPerLine"/>
72
+ <module name="StringLiteralEquality"/>
73
+ <module name="MutableException"/>
74
+ <module name="EqualsHashCode"/>
75
+ <module name="InnerAssignment"/>
76
+ <module name="InterfaceIsType"/>
77
+ <module name="HideUtilityClassConstructor"/>
78
+
79
+ <module name="MemberName"/>
80
+ <module name="LocalVariableName"/>
81
+ <module name="LocalFinalVariableName"/>
82
+ <module name="TypeName"/>
83
+ <module name="PackageName"/>
84
+ <module name="ParameterName"/>
85
+ <module name="StaticVariableName"/>
86
+ <module name="ClassTypeParameterName">
87
+ <property name="format" value="^[A-Z][0-9]?$"/>
88
+ </module>
89
+ <module name="MethodTypeParameterName">
90
+ <property name="format" value="^[A-Z][0-9]?$"/>
91
+ </module>
92
+
93
+ <module name="WhitespaceAround">
94
+ <property name="allowEmptyConstructors" value="true"/>
95
+ <property name="allowEmptyMethods" value="true"/>
96
+ <property name="ignoreEnhancedForColon" value="false"/>
97
+ <property name="tokens" value="
98
+ ASSIGN, BAND, BAND_ASSIGN, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN,
99
+ BXOR, BXOR_ASSIGN, COLON, DIV, DIV_ASSIGN, EQUAL, GE, GT, LAND, LE,
100
+ LITERAL_ASSERT, LITERAL_CATCH, LITERAL_DO, LITERAL_ELSE,
101
+ LITERAL_FINALLY, LITERAL_FOR, LITERAL_IF, LITERAL_RETURN,
102
+ LITERAL_SYNCHRONIZED, LITERAL_TRY, LITERAL_WHILE,
103
+ LOR, LT, MINUS, MINUS_ASSIGN, MOD, MOD_ASSIGN, NOT_EQUAL,
104
+ PLUS, PLUS_ASSIGN, QUESTION, SL, SLIST, SL_ASSIGN, SR, SR_ASSIGN,
105
+ STAR, STAR_ASSIGN, TYPE_EXTENSION_AND"/>
106
+ </module>
107
+ </module>
108
+ </module>
File without changes
@@ -1,6 +1,6 @@
1
- #Wed Jan 13 12:41:02 JST 2016
2
- distributionBase=GRADLE_USER_HOME
3
- distributionPath=wrapper/dists
4
- zipStoreBase=GRADLE_USER_HOME
5
- zipStorePath=wrapper/dists
6
- distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-bin.zip
1
+ #Wed Jan 13 12:41:02 JST 2016
2
+ distributionBase=GRADLE_USER_HOME
3
+ distributionPath=wrapper/dists
4
+ zipStoreBase=GRADLE_USER_HOME
5
+ zipStorePath=wrapper/dists
6
+ distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-bin.zip
data/gradlew CHANGED
File without changes
File without changes
@@ -1 +1 @@
1
- rootProject.name = 'embulk-output-s3'
1
+ rootProject.name = 'embulk-output-s3'
@@ -1,301 +1,298 @@
1
- package org.embulk.output;
2
-
3
- import com.amazonaws.ClientConfiguration;
4
- import com.amazonaws.auth.BasicAWSCredentials;
5
- import com.amazonaws.auth.EnvironmentVariableCredentialsProvider;
6
- import com.amazonaws.services.s3.AmazonS3Client;
7
- import com.amazonaws.services.s3.model.CannedAccessControlList;
8
- import com.amazonaws.services.s3.model.PutObjectRequest;
9
- import com.google.common.base.Optional;
10
- import org.embulk.config.Config;
11
- import org.embulk.config.ConfigDefault;
12
- import org.embulk.config.ConfigDiff;
13
- import org.embulk.config.ConfigException;
14
- import org.embulk.config.ConfigSource;
15
- import org.embulk.config.Task;
16
- import org.embulk.config.TaskReport;
17
- import org.embulk.config.TaskSource;
18
- import org.embulk.spi.Buffer;
19
- import org.embulk.spi.Exec;
20
- import org.embulk.spi.FileOutput;
21
- import org.embulk.spi.FileOutputPlugin;
22
- import org.embulk.spi.TransactionalFileOutput;
23
- import org.slf4j.Logger;
24
-
25
- import java.io.IOException;
26
- import java.io.OutputStream;
27
- import java.nio.file.Files;
28
- import java.nio.file.Path;
29
- import java.util.IllegalFormatException;
30
- import java.util.List;
31
- import java.util.Locale;
32
-
33
- public class S3FileOutputPlugin
34
- implements FileOutputPlugin
35
- {
36
- public interface PluginTask
37
- extends Task
38
- {
39
- @Config("path_prefix")
40
- String getPathPrefix();
41
-
42
- @Config("file_ext")
43
- String getFileNameExtension();
44
-
45
- @Config("sequence_format")
46
- @ConfigDefault("\".%03d.%02d\"")
47
- String getSequenceFormat();
48
-
49
- @Config("bucket")
50
- String getBucket();
51
-
52
- @Config("endpoint")
53
- @ConfigDefault("null")
54
- Optional<String> getEndpoint();
55
-
56
- @Config("access_key_id")
57
- @ConfigDefault("null")
58
- Optional<String> getAccessKeyId();
59
-
60
- @Config("secret_access_key")
61
- @ConfigDefault("null")
62
- Optional<String> getSecretAccessKey();
63
-
64
- @Config("tmp_path_prefix")
65
- @ConfigDefault("\"embulk-output-s3-\"")
66
- String getTempPathPrefix();
67
-
68
- @Config("canned_acl")
69
- @ConfigDefault("null")
70
- Optional<CannedAccessControlList> getCannedAccessControlList();
71
- }
72
-
73
- public static class S3FileOutput
74
- implements FileOutput,
75
- TransactionalFileOutput
76
- {
77
- private final Logger log = Exec.getLogger(S3FileOutputPlugin.class);
78
-
79
- private final String bucket;
80
- private final String pathPrefix;
81
- private final String sequenceFormat;
82
- private final String fileNameExtension;
83
- private final String tempPathPrefix;
84
- private final Optional<CannedAccessControlList> cannedAccessControlListOptional;
85
-
86
- private int taskIndex;
87
- private int fileIndex;
88
- private AmazonS3Client client;
89
- private OutputStream current;
90
- private Path tempFilePath;
91
-
92
- private static AmazonS3Client newS3Client(PluginTask task)
93
- {
94
- AmazonS3Client client;
95
-
96
- if (task.getAccessKeyId().isPresent()) {
97
- BasicAWSCredentials basicAWSCredentials = new BasicAWSCredentials(
98
- task.getAccessKeyId().get(), task.getSecretAccessKey().get());
99
-
100
- ClientConfiguration config = new ClientConfiguration();
101
- // TODO: Support more configurations.
102
-
103
- client = new AmazonS3Client(basicAWSCredentials, config);
104
- }
105
- else {
106
- if (System.getenv("AWS_ACCESS_KEY_ID") == null) {
107
- client = new AmazonS3Client(new EnvironmentVariableCredentialsProvider());
108
- }
109
- else { // IAM ROLE
110
- client = new AmazonS3Client();
111
- }
112
- }
113
- if (task.getEndpoint().isPresent()) {
114
- client.setEndpoint(task.getEndpoint().get());
115
- }
116
-
117
- return client;
118
- }
119
-
120
- public S3FileOutput(PluginTask task, int taskIndex)
121
- {
122
- this.taskIndex = taskIndex;
123
- this.client = newS3Client(task);
124
- this.bucket = task.getBucket();
125
- this.pathPrefix = task.getPathPrefix();
126
- this.sequenceFormat = task.getSequenceFormat();
127
- this.fileNameExtension = task.getFileNameExtension();
128
- this.tempPathPrefix = task.getTempPathPrefix();
129
- this.cannedAccessControlListOptional = task.getCannedAccessControlList();
130
- }
131
-
132
- private static Path newTempFile(String prefix)
133
- throws IOException
134
- {
135
- return Files.createTempFile(prefix, null);
136
- }
137
-
138
- private void deleteTempFile()
139
- {
140
- if (tempFilePath == null) {
141
- return;
142
- }
143
-
144
- try {
145
- Files.delete(tempFilePath);
146
- tempFilePath = null;
147
- }
148
- catch (IOException e) {
149
- throw new RuntimeException(e);
150
- }
151
- }
152
-
153
- private String buildCurrentKey()
154
- {
155
- String sequence = String.format(sequenceFormat, taskIndex,
156
- fileIndex);
157
- return pathPrefix + sequence + fileNameExtension;
158
- }
159
-
160
- private void putFile(Path from, String key)
161
- {
162
- PutObjectRequest request = new PutObjectRequest(bucket, key, from.toFile());
163
- if (cannedAccessControlListOptional.isPresent()) {
164
- request.withCannedAcl(cannedAccessControlListOptional.get());
165
- }
166
- client.putObject(request);
167
- }
168
-
169
- private void closeCurrent()
170
- {
171
- if (current == null) {
172
- return;
173
- }
174
-
175
- try {
176
- putFile(tempFilePath, buildCurrentKey());
177
- fileIndex++;
178
- }
179
- finally {
180
- try {
181
- current.close();
182
- current = null;
183
- }
184
- catch (IOException e) {
185
- throw new RuntimeException(e);
186
- }
187
- finally {
188
- deleteTempFile();
189
- }
190
- }
191
- }
192
-
193
- @Override
194
- public void nextFile()
195
- {
196
- closeCurrent();
197
-
198
- try {
199
- tempFilePath = newTempFile(tempPathPrefix);
200
-
201
- log.info("Writing S3 file '{}'", buildCurrentKey());
202
-
203
- current = Files.newOutputStream(tempFilePath);
204
- }
205
- catch (IOException e) {
206
- throw new RuntimeException(e);
207
- }
208
- }
209
-
210
- @Override
211
- public void add(Buffer buffer)
212
- {
213
- if (current == null) {
214
- throw new IllegalStateException(
215
- "nextFile() must be called before poll()");
216
- }
217
-
218
- try {
219
- current.write(buffer.array(), buffer.offset(), buffer.limit());
220
- }
221
- catch (IOException ex) {
222
- throw new RuntimeException(ex);
223
- }
224
- finally {
225
- buffer.release();
226
- }
227
- }
228
-
229
- @Override
230
- public void finish()
231
- {
232
- closeCurrent();
233
- }
234
-
235
- @Override
236
- public void close()
237
- {
238
- closeCurrent();
239
- }
240
-
241
- @Override
242
- public void abort()
243
- {
244
- deleteTempFile();
245
- }
246
-
247
- @Override
248
- public TaskReport commit()
249
- {
250
- TaskReport report = Exec.newTaskReport();
251
- return report;
252
- }
253
- }
254
-
255
- private void validateSequenceFormat(PluginTask task)
256
- {
257
- try {
258
- @SuppressWarnings("unused")
259
- String dontCare = String.format(Locale.ENGLISH,
260
- task.getSequenceFormat(), 0, 0);
261
- }
262
- catch (IllegalFormatException ex) {
263
- throw new ConfigException(
264
- "Invalid sequence_format: parameter for file output plugin",
265
- ex);
266
- }
267
- }
268
-
269
- @Override
270
- public ConfigDiff transaction(ConfigSource config, int taskCount,
271
- Control control)
272
- {
273
- PluginTask task = config.loadConfig(PluginTask.class);
274
-
275
- validateSequenceFormat(task);
276
-
277
- return resume(task.dump(), taskCount, control);
278
- }
279
-
280
- @Override
281
- public ConfigDiff resume(TaskSource taskSource, int taskCount,
282
- Control control)
283
- {
284
- control.run(taskSource);
285
- return Exec.newConfigDiff();
286
- }
287
-
288
- @Override
289
- public void cleanup(TaskSource taskSource, int taskCount,
290
- List<TaskReport> successTaskReports)
291
- {
292
- }
293
-
294
- @Override
295
- public TransactionalFileOutput open(TaskSource taskSource, int taskIndex)
296
- {
297
- PluginTask task = taskSource.loadTask(PluginTask.class);
298
-
299
- return new S3FileOutput(task, taskIndex);
300
- }
301
- }
1
+ package org.embulk.output;
2
+
3
+ import java.io.IOException;
4
+ import java.io.OutputStream;
5
+ import java.nio.file.Files;
6
+ import java.nio.file.Path;
7
+ import java.util.IllegalFormatException;
8
+ import java.util.List;
9
+ import java.util.Locale;
10
+
11
+ import org.embulk.config.Config;
12
+ import org.embulk.config.ConfigDefault;
13
+ import org.embulk.config.ConfigDiff;
14
+ import org.embulk.config.ConfigException;
15
+ import org.embulk.config.ConfigSource;
16
+ import org.embulk.config.Task;
17
+ import org.embulk.config.TaskReport;
18
+ import org.embulk.config.TaskSource;
19
+ import org.embulk.spi.Buffer;
20
+ import org.embulk.spi.Exec;
21
+ import org.embulk.spi.FileOutput;
22
+ import org.embulk.spi.FileOutputPlugin;
23
+ import org.embulk.spi.TransactionalFileOutput;
24
+ import org.slf4j.Logger;
25
+
26
+ import com.amazonaws.ClientConfiguration;
27
+ import com.amazonaws.auth.BasicAWSCredentials;
28
+ import com.amazonaws.services.s3.AmazonS3Client;
29
+ import com.amazonaws.services.s3.model.CannedAccessControlList;
30
+ import com.amazonaws.services.s3.model.PutObjectRequest;
31
+ import com.google.common.base.Optional;
32
+
33
+ public class S3FileOutputPlugin
34
+ implements FileOutputPlugin
35
+ {
36
+ public interface PluginTask
37
+ extends Task
38
+ {
39
+ @Config("path_prefix")
40
+ String getPathPrefix();
41
+
42
+ @Config("file_ext")
43
+ String getFileNameExtension();
44
+
45
+ @Config("sequence_format")
46
+ @ConfigDefault("\".%03d.%02d\"")
47
+ String getSequenceFormat();
48
+
49
+ @Config("bucket")
50
+ String getBucket();
51
+
52
+ @Config("endpoint")
53
+ @ConfigDefault("null")
54
+ Optional<String> getEndpoint();
55
+
56
+ @Config("access_key_id")
57
+ @ConfigDefault("null")
58
+ Optional<String> getAccessKeyId();
59
+
60
+ @Config("secret_access_key")
61
+ @ConfigDefault("null")
62
+ Optional<String> getSecretAccessKey();
63
+
64
+ @Config("tmp_path_prefix")
65
+ @ConfigDefault("\"embulk-output-s3-\"")
66
+ String getTempPathPrefix();
67
+
68
+ @Config("canned_acl")
69
+ @ConfigDefault("null")
70
+ Optional<CannedAccessControlList> getCannedAccessControlList();
71
+ }
72
+
73
+ public static class S3FileOutput
74
+ implements FileOutput,
75
+ TransactionalFileOutput
76
+ {
77
+ private final Logger log = Exec.getLogger(S3FileOutputPlugin.class);
78
+
79
+ private final String bucket;
80
+ private final String pathPrefix;
81
+ private final String sequenceFormat;
82
+ private final String fileNameExtension;
83
+ private final String tempPathPrefix;
84
+ private final Optional<CannedAccessControlList> cannedAccessControlListOptional;
85
+
86
+ private int taskIndex;
87
+ private int fileIndex;
88
+ private AmazonS3Client client;
89
+ private OutputStream current;
90
+ private Path tempFilePath;
91
+
92
+ private static AmazonS3Client newS3Client(PluginTask task)
93
+ {
94
+ AmazonS3Client client;
95
+
96
+ // TODO: Support more configurations.
97
+ ClientConfiguration config = new ClientConfiguration();
98
+
99
+ if (task.getAccessKeyId().isPresent()) {
100
+ BasicAWSCredentials basicAWSCredentials = new BasicAWSCredentials(
101
+ task.getAccessKeyId().get(), task.getSecretAccessKey().get());
102
+
103
+ client = new AmazonS3Client(basicAWSCredentials, config);
104
+ }
105
+ else {
106
+ // Use default credential provider chain.
107
+ client = new AmazonS3Client(config);
108
+ }
109
+
110
+ if (task.getEndpoint().isPresent()) {
111
+ client.setEndpoint(task.getEndpoint().get());
112
+ }
113
+
114
+ return client;
115
+ }
116
+
117
+ public S3FileOutput(PluginTask task, int taskIndex)
118
+ {
119
+ this.taskIndex = taskIndex;
120
+ this.client = newS3Client(task);
121
+ this.bucket = task.getBucket();
122
+ this.pathPrefix = task.getPathPrefix();
123
+ this.sequenceFormat = task.getSequenceFormat();
124
+ this.fileNameExtension = task.getFileNameExtension();
125
+ this.tempPathPrefix = task.getTempPathPrefix();
126
+ this.cannedAccessControlListOptional = task.getCannedAccessControlList();
127
+ }
128
+
129
+ private static Path newTempFile(String prefix)
130
+ throws IOException
131
+ {
132
+ return Files.createTempFile(prefix, null);
133
+ }
134
+
135
+ private void deleteTempFile()
136
+ {
137
+ if (tempFilePath == null) {
138
+ return;
139
+ }
140
+
141
+ try {
142
+ Files.delete(tempFilePath);
143
+ tempFilePath = null;
144
+ }
145
+ catch (IOException e) {
146
+ throw new RuntimeException(e);
147
+ }
148
+ }
149
+
150
+ private String buildCurrentKey()
151
+ {
152
+ String sequence = String.format(sequenceFormat, taskIndex,
153
+ fileIndex);
154
+ return pathPrefix + sequence + fileNameExtension;
155
+ }
156
+
157
+ private void putFile(Path from, String key)
158
+ {
159
+ PutObjectRequest request = new PutObjectRequest(bucket, key, from.toFile());
160
+ if (cannedAccessControlListOptional.isPresent()) {
161
+ request.withCannedAcl(cannedAccessControlListOptional.get());
162
+ }
163
+ client.putObject(request);
164
+ }
165
+
166
+ private void closeCurrent()
167
+ {
168
+ if (current == null) {
169
+ return;
170
+ }
171
+
172
+ try {
173
+ putFile(tempFilePath, buildCurrentKey());
174
+ fileIndex++;
175
+ }
176
+ finally {
177
+ try {
178
+ current.close();
179
+ current = null;
180
+ }
181
+ catch (IOException e) {
182
+ throw new RuntimeException(e);
183
+ }
184
+ finally {
185
+ deleteTempFile();
186
+ }
187
+ }
188
+ }
189
+
190
+ @Override
191
+ public void nextFile()
192
+ {
193
+ closeCurrent();
194
+
195
+ try {
196
+ tempFilePath = newTempFile(tempPathPrefix);
197
+
198
+ log.info("Writing S3 file '{}'", buildCurrentKey());
199
+
200
+ current = Files.newOutputStream(tempFilePath);
201
+ }
202
+ catch (IOException e) {
203
+ throw new RuntimeException(e);
204
+ }
205
+ }
206
+
207
+ @Override
208
+ public void add(Buffer buffer)
209
+ {
210
+ if (current == null) {
211
+ throw new IllegalStateException(
212
+ "nextFile() must be called before poll()");
213
+ }
214
+
215
+ try {
216
+ current.write(buffer.array(), buffer.offset(), buffer.limit());
217
+ }
218
+ catch (IOException ex) {
219
+ throw new RuntimeException(ex);
220
+ }
221
+ finally {
222
+ buffer.release();
223
+ }
224
+ }
225
+
226
+ @Override
227
+ public void finish()
228
+ {
229
+ closeCurrent();
230
+ }
231
+
232
+ @Override
233
+ public void close()
234
+ {
235
+ closeCurrent();
236
+ }
237
+
238
+ @Override
239
+ public void abort()
240
+ {
241
+ deleteTempFile();
242
+ }
243
+
244
+ @Override
245
+ public TaskReport commit()
246
+ {
247
+ TaskReport report = Exec.newTaskReport();
248
+ return report;
249
+ }
250
+ }
251
+
252
+ private void validateSequenceFormat(PluginTask task)
253
+ {
254
+ try {
255
+ @SuppressWarnings("unused")
256
+ String dontCare = String.format(Locale.ENGLISH,
257
+ task.getSequenceFormat(), 0, 0);
258
+ }
259
+ catch (IllegalFormatException ex) {
260
+ throw new ConfigException(
261
+ "Invalid sequence_format: parameter for file output plugin",
262
+ ex);
263
+ }
264
+ }
265
+
266
+ @Override
267
+ public ConfigDiff transaction(ConfigSource config, int taskCount,
268
+ Control control)
269
+ {
270
+ PluginTask task = config.loadConfig(PluginTask.class);
271
+
272
+ validateSequenceFormat(task);
273
+
274
+ return resume(task.dump(), taskCount, control);
275
+ }
276
+
277
+ @Override
278
+ public ConfigDiff resume(TaskSource taskSource, int taskCount,
279
+ Control control)
280
+ {
281
+ control.run(taskSource);
282
+ return Exec.newConfigDiff();
283
+ }
284
+
285
+ @Override
286
+ public void cleanup(TaskSource taskSource, int taskCount,
287
+ List<TaskReport> successTaskReports)
288
+ {
289
+ }
290
+
291
+ @Override
292
+ public TransactionalFileOutput open(TaskSource taskSource, int taskIndex)
293
+ {
294
+ PluginTask task = taskSource.loadTask(PluginTask.class);
295
+
296
+ return new S3FileOutput(task, taskIndex);
297
+ }
298
+ }