embulk-input-http 0.0.15 → 0.0.17

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 62da7af46d26103cf5afdcb94b6fb1c807e26c38
4
- data.tar.gz: ad8323dab3583326adbcff02408d3eaa3bc8e2a2
3
+ metadata.gz: 41ace198c24c4c60e9d0266b03480091398fda2e
4
+ data.tar.gz: a18099e41b799416545996dd6f2518591061ca21
5
5
  SHA512:
6
- metadata.gz: a8a0e35550e2dd0df465a9b08bd916463676eb818eb1fe00c7279dc799c367e8be5949b04cc513ed4b21fbd01b65fcc7568c3141c27fc5fb58ec556c663e0945
7
- data.tar.gz: aa5b119f9a2f29ff4ce01a3b548149ede29de765c8e0431a64862f053646b9bc4f67320299341526de695d56237972b44f53ce710a1349dd6fb642b153a3c4b1
6
+ metadata.gz: 81e9f5146533fe1944b896ecfe81f4fdc929eda9a16c5917c65cda83c65f0a89b6b2005ee5bc2d19cc04b2b21207810e4f55650ca646a6825868658578dbbd63
7
+ data.tar.gz: 2004dd879f0518827f4d00ec824bbf26901a469df511443a6b90b48a8102796c65725f193fd36b81f7d874d6a3bb6dc81c19aaf1db91c25e270f1b3e01aceed1
data/README.md CHANGED
@@ -34,14 +34,15 @@ in:
34
34
  - **method**: http method, get is used by default (optional)
35
35
  - **user_agent**: the usrr agent to specify request header (optional)
36
36
  - **request_headers**: the extra request headers as key-value (optional)
37
- - **charset**: charset to specify request header (optional, utf-8 is used by default)
37
+ - **charset**: charset to specify request header (optional, default: utf8)
38
38
  - **basic_auth**: username/password for basic authentication (optional)
39
- - **open_timeout**: timeout msec to open connection (optional, 2000 is used by default)
40
- - **read_timeout**: timeout msec to read content via http (optional, 10000 is used by default)
41
- - **max_retries**: max number of retry request if failed (optional, 5 is used by default)
42
- - **retry_interval**: interval msec to retry max (optional, 10000 is used by default)
43
- - **request_interval**: wait msec before each requests (optional, 0 is used by default)
44
- - **interval\_includes\_response\_time**: yes/no, if yes and you set *request_interval*, response time will be included in interval for next request (optional, no is used by default)
39
+ - **open_timeout**: timeout msec to open connection (optional, default: 2000)
40
+ - **read_timeout**: timeout msec to read content via http (optional, default: 10000)
41
+ - **max_retries**: max number of retry request if failed (optional, default: 5)
42
+ - **retry_interval**: interval msec to retry max (optional, default: 10000)
43
+ - **request_interval**: wait msec before each requests (optional, default: 0)
44
+ - **interval\_includes\_response\_time**: yes/no, if yes and you set *request_interval*, response time will be included in interval for next request (optional, default: no)
45
+ - **direct\_input**: If false, dumps content to temp file first, to avoid read timeout due to process large data while dowoloading from remote (optional, default: true)
45
46
 
46
47
  ### Brace expansion style in 'params'
47
48
 
@@ -74,8 +75,8 @@ You can specify username/password for basic authentication.
74
75
 
75
76
  ```yaml
76
77
  basic_auth:
77
- - user: MyUser
78
- - password: MyPassword
78
+ user: MyUser
79
+ password: MyPassword
79
80
  ```
80
81
 
81
82
  ### Paging by 'pager'
data/build.gradle CHANGED
@@ -13,15 +13,16 @@ configurations {
13
13
  provided
14
14
  }
15
15
 
16
- version = "0.0.15"
16
+ version = "0.0.17"
17
17
 
18
18
  sourceCompatibility = 1.7
19
19
  targetCompatibility = 1.7
20
20
 
21
21
  dependencies {
22
22
  compile "org.embulk:embulk-core:0.8.8"
23
- compile "org.apache.httpcomponents:httpclient:4.5"
24
23
  provided "org.embulk:embulk-core:0.8.8"
24
+ compile "org.apache.httpcomponents:httpclient:4.5"
25
+ compile "commons-io:commons-io:2.5"
25
26
  testCompile "junit:junit:4.+"
26
27
  }
27
28
 
@@ -49,13 +50,24 @@ task checkstyle(type: Checkstyle) {
49
50
  source = sourceSets.main.allJava + sourceSets.test.allJava
50
51
  }
51
52
 
52
- task gem(type: JRubyExec, dependsOn: ["build", "gemspec", "classpath"]) {
53
+ task gem(type: JRubyExec, dependsOn: ["gemspec", "classpath"]) {
53
54
  jrubyArgs "-rrubygems/gem_runner", "-eGem::GemRunner.new.run(ARGV)", "build"
54
- script "build/gemspec"
55
+ script "${project.name}.gemspec"
55
56
  doLast { ant.move(file: "${project.name}-${project.version}.gem", todir: "pkg") }
56
57
  }
57
58
 
58
- task gemspec << { file("build/gemspec").write($/
59
+ task gemPush(type: JRubyExec, dependsOn: ["gem"]) {
60
+ jrubyArgs "-rrubygems/gem_runner", "-eGem::GemRunner.new.run(ARGV)", "push"
61
+ script "pkg/${project.name}-${project.version}.gem"
62
+ }
63
+
64
+ task "package"(dependsOn: ["gemspec", "classpath"]) << {
65
+ println "> Build succeeded."
66
+ println "> You can run embulk with '-L ${file(".").absolutePath}' argument."
67
+ }
68
+
69
+
70
+ task gemspec << { file("${project.name}.gemspec").write($/
59
71
  Gem::Specification.new do |spec|
60
72
  spec.name = "${project.name}"
61
73
  spec.version = "${project.version}"
Binary file
@@ -0,0 +1,17 @@
1
+
2
+ Gem::Specification.new do |spec|
3
+ spec.name = "embulk-input-http"
4
+ spec.version = "0.0.17"
5
+ spec.authors = ["Takuma kanari"]
6
+ spec.email = ["chemtrails.t@gmail.com"]
7
+ spec.summary = %q{Embulk plugin for http input}
8
+ spec.description = %q{Fetch data via http}
9
+ spec.homepage = "https://github.com/takumakanari/embulk-input-http"
10
+ spec.license = "MIT"
11
+
12
+ spec.files = `git ls-files`.split("\n") + Dir["classpath/*.jar"]
13
+ spec.test_files = spec.files.grep(%r"^(test|spec)/")
14
+ spec.require_paths = ["lib"]
15
+ spec.add_development_dependency 'bundler', ['~> 1.0']
16
+ spec.add_development_dependency 'rake', ['>= 10.0']
17
+ end
@@ -14,6 +14,7 @@ in:
14
14
  interval_includes_response_time: 1
15
15
  request_headers: {X-Some-Key1: some-value1, X-Some-key2: some-value2}
16
16
  pager: {from_param: from, to_param: to, pages: 10, step: 100}
17
+ # input_direct: false
17
18
  parser:
18
19
  type: none
19
20
 
@@ -4,36 +4,40 @@ import com.fasterxml.jackson.annotation.JsonCreator;
4
4
  import com.fasterxml.jackson.annotation.JsonProperty;
5
5
  import com.google.common.base.Objects;
6
6
 
7
- public class BasicAuthConfig {
8
-
7
+ public class BasicAuthOption
8
+ {
9
9
  private final String user;
10
10
  private final String password;
11
11
 
12
12
  @JsonCreator
13
- public BasicAuthConfig(
14
- @JsonProperty("user") String user,
15
- @JsonProperty("password") String password) {
13
+ public BasicAuthOption(@JsonProperty("user") String user,
14
+ @JsonProperty("password") String password)
15
+ {
16
16
  this.user = user;
17
17
  this.password = password;
18
18
  }
19
19
 
20
20
  @JsonProperty("user")
21
- public String getUser() {
21
+ public String getUser()
22
+ {
22
23
  return user;
23
24
  }
24
25
 
25
26
  @JsonProperty("password")
26
- public String getPassword() {
27
+ public String getPassword()
28
+ {
27
29
  return password;
28
30
  }
29
31
 
30
32
  @Override
31
- public int hashCode() {
33
+ public int hashCode()
34
+ {
32
35
  return Objects.hashCode(user, password);
33
36
  }
34
37
 
35
38
  @Override
36
- public String toString() {
37
- return String.format("BasicAuthConfig[%s, %s]", getUser(), getPassword());
39
+ public String toString()
40
+ {
41
+ return String.format("BasicAuthOption[%s, %s]", getUser(), getPassword());
38
42
  }
39
43
  }
@@ -3,6 +3,7 @@ package org.embulk.input.http;
3
3
  import com.google.common.base.Optional;
4
4
  import com.google.common.base.Throwables;
5
5
  import com.google.common.collect.Lists;
6
+ import org.apache.commons.io.IOUtils;
6
7
  import org.apache.http.Header;
7
8
  import org.apache.http.NameValuePair;
8
9
  import org.apache.http.auth.AuthScope;
@@ -19,7 +20,14 @@ import org.apache.http.impl.client.BasicCredentialsProvider;
19
20
  import org.apache.http.impl.client.HttpClientBuilder;
20
21
  import org.apache.http.message.BasicHeader;
21
22
  import org.apache.http.message.BasicNameValuePair;
22
- import org.embulk.config.*;
23
+ import org.embulk.config.Config;
24
+ import org.embulk.config.ConfigDefault;
25
+ import org.embulk.config.ConfigDiff;
26
+ import org.embulk.config.ConfigInject;
27
+ import org.embulk.config.ConfigSource;
28
+ import org.embulk.config.Task;
29
+ import org.embulk.config.TaskReport;
30
+ import org.embulk.config.TaskSource;
23
31
  import org.embulk.spi.BufferAllocator;
24
32
  import org.embulk.spi.Exec;
25
33
  import org.embulk.spi.FileInputPlugin;
@@ -28,108 +36,124 @@ import org.embulk.spi.util.InputStreamFileInput;
28
36
  import org.embulk.spi.util.RetryExecutor;
29
37
  import org.slf4j.Logger;
30
38
 
39
+ import java.io.File;
40
+ import java.io.FileInputStream;
41
+ import java.io.FileOutputStream;
31
42
  import java.io.IOException;
32
43
  import java.io.InputStream;
33
44
  import java.io.UnsupportedEncodingException;
34
45
  import java.net.URISyntaxException;
46
+ import java.nio.file.Files;
35
47
  import java.util.ArrayList;
36
48
  import java.util.List;
49
+ import java.util.Locale;
37
50
  import java.util.Map;
38
51
 
39
- public class HttpFileInputPlugin implements FileInputPlugin {
52
+ import static java.lang.String.format;
40
53
 
54
+ public class HttpFileInputPlugin implements FileInputPlugin
55
+ {
41
56
  private final Logger logger = Exec.getLogger(getClass());
42
57
 
43
- public interface PluginTask extends Task {
58
+ public interface PluginTask extends Task
59
+ {
44
60
  @Config("url")
45
- public String getUrl();
61
+ String getUrl();
46
62
 
47
63
  @Config("charset")
48
64
  @ConfigDefault("\"utf-8\"")
49
- public String getCharset();
65
+ String getCharset();
50
66
 
51
67
  @Config("method")
52
68
  @ConfigDefault("\"get\"")
53
- public String getMethod();
69
+ String getMethod();
54
70
 
55
71
  @Config("user_agent")
56
72
  @ConfigDefault("\"Embulk::Input::HttpFileInputPlugin\"")
57
- public String getUserAgent();
73
+ String getUserAgent();
58
74
 
59
75
  @Config("open_timeout")
60
76
  @ConfigDefault("2000")
61
- public int getOpenTimeout();
77
+ int getOpenTimeout();
62
78
 
63
79
  @Config("read_timeout")
64
80
  @ConfigDefault("10000")
65
- public int getReadTimeout();
81
+ int getReadTimeout();
66
82
 
67
83
  @Config("max_retries")
68
84
  @ConfigDefault("5")
69
- public int getMaxRetries();
85
+ int getMaxRetries();
70
86
 
71
87
  @Config("retry_interval")
72
88
  @ConfigDefault("10000")
73
- public int getRetryInterval();
89
+ int getRetryInterval();
74
90
 
75
91
  @Config("request_interval")
76
92
  @ConfigDefault("0")
77
- public int getRequestInterval();
93
+ int getRequestInterval();
78
94
 
79
- public void setRequestInterval(int requestInterval);
95
+ void setRequestInterval(int requestInterval);
80
96
 
81
97
  @Config("interval_includes_response_time")
82
98
  @ConfigDefault("null")
83
- public boolean getIntervalIncludesResponseTime();
99
+ boolean getIntervalIncludesResponseTime();
100
+
101
+ @Config("input_direct")
102
+ @ConfigDefault("true")
103
+ boolean getInputDirect();
84
104
 
85
105
  @Config("params")
86
106
  @ConfigDefault("null")
87
- public Optional<ParamsConfig> getParams();
107
+ Optional<ParamsOption> getParams();
88
108
 
89
109
  @Config("basic_auth")
90
110
  @ConfigDefault("null")
91
- public Optional<BasicAuthConfig> getBasicAuth();
111
+ Optional<BasicAuthOption> getBasicAuth();
92
112
 
93
113
  @Config("pager")
94
114
  @ConfigDefault("null")
95
- public Optional<PagerConfig> getPager();
115
+ Optional<PagerOption> getPager();
96
116
 
97
117
  @Config("request_headers")
98
118
  @ConfigDefault("{}")
99
- public Map<String, String> getRequestHeaders();
119
+ Map<String, String> getRequestHeaders();
100
120
 
101
121
  @ConfigInject
102
- public BufferAllocator getBufferAllocator();
122
+ BufferAllocator getBufferAllocator();
103
123
 
104
- public List<List<QueryConfig.Query>> getQueries();
124
+ List<List<QueryOption.Query>> getQueries();
105
125
 
106
- public void setQueries(List<List<QueryConfig.Query>> queries);
126
+ void setQueries(List<List<QueryOption.Query>> queries);
107
127
 
108
- public HttpMethod getHttpMethod();
128
+ HttpMethod getHttpMethod();
109
129
 
110
- public void setHttpMethod(HttpMethod httpMethod);
130
+ void setHttpMethod(HttpMethod httpMethod);
111
131
  }
112
132
 
113
- public enum HttpMethod {
133
+ public enum HttpMethod
134
+ {
114
135
  POST,
115
136
  GET
116
137
  }
117
138
 
118
139
  @Override
119
- public ConfigDiff transaction(ConfigSource config, FileInputPlugin.Control control) {
140
+ public ConfigDiff transaction(ConfigSource config, FileInputPlugin.Control control)
141
+ {
120
142
  PluginTask task = config.loadConfig(PluginTask.class);
121
143
 
122
144
  final int tasks;
123
145
  if (task.getParams().isPresent()) {
124
- List<List<QueryConfig.Query>> queries = task.getParams().get().generateQueries(task.getPager());
146
+ List<List<QueryOption.Query>> queries = task.getParams().get().generateQueries(task.getPager());
125
147
  task.setQueries(queries);
126
148
  tasks = queries.size();
127
- } else if (task.getPager().isPresent()) {
128
- List<List<QueryConfig.Query>> queries = task.getPager().get().expand();
149
+ }
150
+ else if (task.getPager().isPresent()) {
151
+ List<List<QueryOption.Query>> queries = task.getPager().get().expand();
129
152
  task.setQueries(queries);
130
153
  tasks = queries.size();
131
- } else {
132
- task.setQueries(Lists.<List<QueryConfig.Query>>newArrayList());
154
+ }
155
+ else {
156
+ task.setQueries(Lists.<List<QueryOption.Query>>newArrayList());
133
157
  task.setRequestInterval(0);
134
158
  tasks = 1;
135
159
  }
@@ -140,25 +164,27 @@ public class HttpFileInputPlugin implements FileInputPlugin {
140
164
  }
141
165
 
142
166
  @Override
143
- public ConfigDiff resume(TaskSource taskSource,
144
- int taskCount,
145
- FileInputPlugin.Control control) {
167
+ public ConfigDiff resume(TaskSource taskSource, int taskCount, FileInputPlugin.Control control)
168
+ {
146
169
  control.run(taskSource, taskCount);
147
170
  return Exec.newConfigDiff();
148
171
  }
149
172
 
150
173
  @Override
151
- public void cleanup(TaskSource taskSource, int taskCount, List<TaskReport> successTaskReports) {
174
+ public void cleanup(TaskSource taskSource, int taskCount, List<TaskReport> successTaskReports)
175
+ {
152
176
  }
153
177
 
154
178
  @Override
155
- public TransactionalFileInput open(TaskSource taskSource, int taskIndex) {
179
+ public TransactionalFileInput open(TaskSource taskSource, int taskIndex)
180
+ {
156
181
  PluginTask task = taskSource.loadTask(PluginTask.class);
157
182
 
158
183
  HttpRequestBase request;
159
184
  try {
160
185
  request = makeRequest(task, taskIndex);
161
- } catch (URISyntaxException | UnsupportedEncodingException e) {
186
+ }
187
+ catch (URISyntaxException | UnsupportedEncodingException e) {
162
188
  throw Throwables.propagate(e);
163
189
  }
164
190
 
@@ -173,8 +199,7 @@ public class HttpFileInputPlugin implements FileInputPlugin {
173
199
 
174
200
  HttpClient client = builder.build();
175
201
 
176
- logger.info(String.format("%s \"%s\"", task.getMethod().toUpperCase(),
177
- request.getURI().toString()));
202
+ logger.info(format(Locale.ENGLISH, "%s \"%s\"", task.getMethod().toUpperCase(), request.getURI().toString()));
178
203
 
179
204
  RetryableHandler retryable = new RetryableHandler(client, request);
180
205
  long startTimeMills = System.currentTimeMillis();
@@ -184,33 +209,57 @@ public class HttpFileInputPlugin implements FileInputPlugin {
184
209
  withInitialRetryWait(task.getRetryInterval()).
185
210
  withMaxRetryWait(30 * 60 * 1000).
186
211
  runInterruptible(retryable);
212
+
187
213
  InputStream stream = retryable.getResponse().getEntity().getContent();
214
+ if (!task.getInputDirect()) {
215
+ stream = copyToFile(stream);
216
+ }
217
+
188
218
  PluginFileInput input = new PluginFileInput(task, stream, startTimeMills);
189
219
  stream = null;
190
220
  return input;
191
- } catch (Exception e) {
221
+ }
222
+ catch (Exception e) {
192
223
  throw Throwables.propagate(e);
193
224
  }
194
225
  }
195
226
 
196
- private CredentialsProvider makeCredentialsProvider(BasicAuthConfig config, HttpRequestBase scopeRequest) {
227
+ private InputStream copyToFile(InputStream input)
228
+ throws IOException
229
+ {
230
+ File tmpfile = Files.createTempFile("embulk-input-http.", ".tmp").toFile();
231
+ tmpfile.deleteOnExit();
232
+
233
+ try (FileOutputStream output = new FileOutputStream(tmpfile)) {
234
+ logger.info(format(Locale.ENGLISH, "Writing response to %s", tmpfile));
235
+ IOUtils.copy(input, output);
236
+ } finally {
237
+ input.close();
238
+ }
239
+
240
+ return new FileInputStream(tmpfile);
241
+ }
242
+
243
+ private CredentialsProvider makeCredentialsProvider(BasicAuthOption basicAuth, HttpRequestBase request)
244
+ {
197
245
  final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
198
- final AuthScope authScope = new AuthScope(scopeRequest.getURI().getHost(),
199
- scopeRequest.getURI().getPort());
246
+ final AuthScope authScope = new AuthScope(request.getURI().getHost(),
247
+ request.getURI().getPort());
200
248
  credentialsProvider.setCredentials(authScope,
201
- new UsernamePasswordCredentials(config.getUser(), config.getPassword()));
249
+ new UsernamePasswordCredentials(basicAuth.getUser(), basicAuth.getPassword()));
202
250
  return credentialsProvider;
203
251
  }
204
252
 
205
253
  private HttpRequestBase makeRequest(PluginTask task, int taskIndex)
206
- throws URISyntaxException, UnsupportedEncodingException {
207
- final List<QueryConfig.Query> queries = (task.getQueries().isEmpty()) ?
254
+ throws URISyntaxException, UnsupportedEncodingException
255
+ {
256
+ final List<QueryOption.Query> queries = (task.getQueries().isEmpty()) ?
208
257
  null : task.getQueries().get(taskIndex);
209
258
  if (task.getHttpMethod() == HttpMethod.GET) {
210
259
  HttpGet request = new HttpGet(task.getUrl());
211
260
  if (queries != null) {
212
261
  URIBuilder builder = new URIBuilder(request.getURI());
213
- for (QueryConfig.Query q : queries) {
262
+ for (QueryOption.Query q : queries) {
214
263
  for (String v : q.getValues()) {
215
264
  builder.addParameter(q.getName(), v);
216
265
  }
@@ -218,11 +267,12 @@ public class HttpFileInputPlugin implements FileInputPlugin {
218
267
  request.setURI(builder.build());
219
268
  }
220
269
  return request;
221
- } else if (task.getHttpMethod() == HttpMethod.POST) {
270
+ }
271
+ else if (task.getHttpMethod() == HttpMethod.POST) {
222
272
  HttpPost request = new HttpPost(task.getUrl());
223
273
  if (queries != null) {
224
274
  List<NameValuePair> pairs = new ArrayList<>();
225
- for (QueryConfig.Query q : queries) {
275
+ for (QueryOption.Query q : queries) {
226
276
  for (String v : q.getValues()) {
227
277
  pairs.add(new BasicNameValuePair(q.getName(), v));
228
278
  }
@@ -234,7 +284,8 @@ public class HttpFileInputPlugin implements FileInputPlugin {
234
284
  throw new IllegalArgumentException(String.format("Unsupported http method %s", task.getMethod()));
235
285
  }
236
286
 
237
- private List<Header> makeHeaders(PluginTask task) {
287
+ private List<Header> makeHeaders(PluginTask task)
288
+ {
238
289
  List<Header> headers = new ArrayList<>();
239
290
  headers.add(new BasicHeader("Accept", "*/*"));
240
291
  headers.add(new BasicHeader("Accept-Charset", task.getCharset()));
@@ -247,7 +298,8 @@ public class HttpFileInputPlugin implements FileInputPlugin {
247
298
  return headers;
248
299
  }
249
300
 
250
- private RequestConfig makeRequestConfig(PluginTask task) {
301
+ private RequestConfig makeRequestConfig(PluginTask task)
302
+ {
251
303
  return RequestConfig.custom()
252
304
  .setCircularRedirectsAllowed(true)
253
305
  .setMaxRedirects(10)
@@ -258,34 +310,39 @@ public class HttpFileInputPlugin implements FileInputPlugin {
258
310
  }
259
311
 
260
312
  public static class PluginFileInput extends InputStreamFileInput
261
- implements TransactionalFileInput {
262
-
313
+ implements TransactionalFileInput
314
+ {
263
315
  private final Logger logger = Exec.getLogger(getClass());
264
316
 
265
317
  private final long startTimeMills;
266
318
  private final PluginTask task;
267
319
 
268
- public PluginFileInput(PluginTask task, InputStream stream, long startTimeMills) {
320
+ public PluginFileInput(PluginTask task, InputStream stream, long startTimeMills)
321
+ {
269
322
  super(task.getBufferAllocator(), new SingleFileProvider(stream));
270
323
  this.startTimeMills = startTimeMills;
271
324
  this.task = task;
272
325
  }
273
326
 
274
- public TaskReport commit() {
327
+ public TaskReport commit()
328
+ {
275
329
  return Exec.newTaskReport();
276
330
  }
277
331
 
278
332
  @Override
279
- public void close() {
333
+ public void close()
334
+ {
280
335
  super.close();
281
336
  handleInterval();
282
337
  }
283
338
 
284
339
  @Override
285
- public void abort() {
340
+ public void abort()
341
+ {
286
342
  }
287
343
 
288
- protected void handleInterval() {
344
+ protected void handleInterval()
345
+ {
289
346
  if (task.getRequestInterval() <= 0) {
290
347
  return;
291
348
  }
@@ -297,24 +354,27 @@ public class HttpFileInputPlugin implements FileInputPlugin {
297
354
  logger.info(String.format("waiting %d msec ...", interval));
298
355
  try {
299
356
  Thread.sleep(interval);
300
- } catch (InterruptedException e) {
301
- Throwables.propagate(e);
357
+ }
358
+ catch (InterruptedException e) {
359
+ throw Throwables.propagate(e);
302
360
  }
303
361
  }
304
362
  }
305
363
 
306
364
  private static class SingleFileProvider
307
- implements InputStreamFileInput.Provider {
308
-
365
+ implements InputStreamFileInput.Provider
366
+ {
309
367
  private final InputStream stream;
310
368
  private boolean opened = false;
311
369
 
312
- public SingleFileProvider(InputStream stream) {
370
+ public SingleFileProvider(InputStream stream)
371
+ {
313
372
  this.stream = stream;
314
373
  }
315
374
 
316
375
  @Override
317
- public InputStream openNext() throws IOException {
376
+ public InputStream openNext() throws IOException
377
+ {
318
378
  if (opened) {
319
379
  return null;
320
380
  }
@@ -323,7 +383,8 @@ public class HttpFileInputPlugin implements FileInputPlugin {
323
383
  }
324
384
 
325
385
  @Override
326
- public void close() throws IOException {
386
+ public void close() throws IOException
387
+ {
327
388
  if (!opened) {
328
389
  stream.close();
329
390
  }