embulk-output-ftp 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,456 @@
1
+ package org.embulk.output.ftp;
2
+
3
+ import com.google.common.base.Optional;
4
+ import com.google.common.base.Throwables;
5
+ import it.sauronsoftware.ftp4j.FTPAbortedException;
6
+ import it.sauronsoftware.ftp4j.FTPClient;
7
+ import it.sauronsoftware.ftp4j.FTPCommunicationListener;
8
+ import it.sauronsoftware.ftp4j.FTPConnector;
9
+ import it.sauronsoftware.ftp4j.FTPDataTransferException;
10
+ import it.sauronsoftware.ftp4j.FTPDataTransferListener;
11
+ import it.sauronsoftware.ftp4j.FTPException;
12
+ import it.sauronsoftware.ftp4j.FTPIllegalReplyException;
13
+ import org.embulk.config.Config;
14
+ import org.embulk.config.ConfigDefault;
15
+ import org.embulk.config.ConfigDiff;
16
+ import org.embulk.config.ConfigException;
17
+ import org.embulk.config.ConfigSource;
18
+ import org.embulk.config.Task;
19
+ import org.embulk.config.TaskReport;
20
+ import org.embulk.config.TaskSource;
21
+ import org.embulk.output.ftp.SSLPlugins.SSLPluginConfig;
22
+ import org.embulk.spi.Buffer;
23
+ import org.embulk.spi.Exec;
24
+ import org.embulk.spi.FileOutputPlugin;
25
+ import org.embulk.spi.TransactionalFileOutput;
26
+ import org.embulk.spi.util.RetryExecutor.RetryGiveupException;
27
+ import org.embulk.spi.util.RetryExecutor.Retryable;
28
+ import org.slf4j.Logger;
29
+ import static org.embulk.spi.util.RetryExecutor.retryExecutor;
30
+
31
+ import java.io.BufferedInputStream;
32
+ import java.io.BufferedOutputStream;
33
+ import java.io.File;
34
+ import java.io.FileInputStream;
35
+ import java.io.FileNotFoundException;
36
+ import java.io.FileOutputStream;
37
+ import java.io.IOException;
38
+ import java.net.URISyntaxException;
39
+ import java.util.List;
40
+
41
+ public class FtpFileOutputPlugin implements FileOutputPlugin
42
+ {
43
+ public interface PluginTask extends Task, SSLPlugins.SSLPluginTask
44
+ {
45
+ @Config("host")
46
+ String getHost();
47
+
48
+ @Config("port")
49
+ @ConfigDefault("null")
50
+ Optional<Integer> getPort();
51
+ void setPort(Optional<Integer> port);
52
+
53
+ @Config("user")
54
+ @ConfigDefault("null")
55
+ Optional<String> getUser();
56
+
57
+ @Config("password")
58
+ @ConfigDefault("null")
59
+ Optional<String> getPassword();
60
+
61
+ @Config("passive_mode")
62
+ @ConfigDefault("true")
63
+ boolean getPassiveMode();
64
+
65
+ @Config("ascii_mode")
66
+ @ConfigDefault("false")
67
+ boolean getAsciiMode();
68
+
69
+ @Config("ssl")
70
+ @ConfigDefault("false")
71
+ boolean getSsl();
72
+
73
+ SSLPluginConfig getSSLConfig();
74
+ void setSSLConfig(SSLPluginConfig config);
75
+
76
+ @Config("path_prefix")
77
+ String getPathPrefix();
78
+
79
+ @Config("file_ext")
80
+ String getFileNameExtension();
81
+
82
+ @Config("sequence_format")
83
+ @ConfigDefault("\"%03d.%02d\"")
84
+ String getSequenceFormat();
85
+
86
+ @Config("max_connection_retry")
87
+ @ConfigDefault("10") // 10 times retry to connect FTP server if failed.
88
+ int getMaxConnectionRetry();
89
+ }
90
+
91
+ private static final Logger log = Exec.getLogger(FtpFileOutputPlugin.class);
92
+ private static final long TRANSFER_NOTICE_BYTES = 100 * 1024 * 1024;
93
+
94
+ @Override
95
+ public ConfigDiff transaction(ConfigSource config, int taskCount, FileOutputPlugin.Control control)
96
+ {
97
+ PluginTask task = config.loadConfig(PluginTask.class);
98
+ task.setSSLConfig(SSLPlugins.configure(task));
99
+
100
+ // try to check if plugin could connect to FTP server
101
+ FTPClient client = null;
102
+ try {
103
+ client = newFTPClient(log, task);
104
+ }
105
+ catch (Exception ex) {
106
+ throw new ConfigException(ex);
107
+ }
108
+ finally {
109
+ disconnectClient(client);
110
+ }
111
+
112
+ return resume(task.dump(), taskCount, control);
113
+ }
114
+
115
+ @Override
116
+ public ConfigDiff resume(TaskSource taskSource, int taskCount, FileOutputPlugin.Control control)
117
+ {
118
+ control.run(taskSource);
119
+
120
+ return Exec.newConfigDiff();
121
+ }
122
+
123
+ @Override
124
+ public void cleanup(TaskSource taskSource, int taskCount, List<TaskReport> successTaskReports)
125
+ {
126
+ }
127
+
128
+ @Override
129
+ public TransactionalFileOutput open(TaskSource taskSource, final int taskIndex)
130
+ {
131
+ final PluginTask task = taskSource.loadTask(PluginTask.class);
132
+
133
+ FTPClient client = newFTPClient(log, task);
134
+ return new FtpFileOutput(client, task, taskIndex);
135
+ }
136
+
137
+ public static class FtpFileOutput implements TransactionalFileOutput
138
+ {
139
+ private final FTPClient client;
140
+ private final String pathPrefix;
141
+ private final String sequenceFormat;
142
+ private final String pathSuffix;
143
+ private final int maxConnectionRetry;
144
+ private BufferedOutputStream output = null;
145
+ private int fileIndex;
146
+ private File file;
147
+ private String filePath;
148
+ private int taskIndex;
149
+
150
+ public FtpFileOutput(FTPClient client, PluginTask task, int taskIndex)
151
+ {
152
+ this.client = client;
153
+ this.taskIndex = taskIndex;
154
+ this.pathPrefix = task.getPathPrefix();
155
+ this.sequenceFormat = task.getSequenceFormat();
156
+ this.pathSuffix = task.getFileNameExtension();
157
+ this.maxConnectionRetry = task.getMaxConnectionRetry();
158
+ }
159
+
160
+ @Override
161
+ public void nextFile()
162
+ {
163
+ closeFile();
164
+
165
+ try {
166
+ String suffix = pathSuffix;
167
+ if (!suffix.startsWith(".")) {
168
+ suffix = "." + suffix;
169
+ }
170
+ filePath = pathPrefix + String.format(sequenceFormat, taskIndex, fileIndex) + suffix;
171
+ file = File.createTempFile(filePath, ".tmp");
172
+ log.info("Writing local file {}", file.getAbsolutePath());
173
+ output = new BufferedOutputStream(new FileOutputStream(file));
174
+ }
175
+ catch (IOException ex) {
176
+ throw Throwables.propagate(ex);
177
+ }
178
+ }
179
+
180
+ private void closeFile()
181
+ {
182
+ if (output != null) {
183
+ try {
184
+ output.close();
185
+ fileIndex++;
186
+ }
187
+ catch (IOException ex) {
188
+ throw Throwables.propagate(ex);
189
+ }
190
+ }
191
+ }
192
+
193
+ @Override
194
+ public void add(Buffer buffer)
195
+ {
196
+ try {
197
+ output.write(buffer.array(), buffer.offset(), buffer.limit());
198
+ }
199
+ catch (IOException ex) {
200
+ throw Throwables.propagate(ex);
201
+ }
202
+ finally {
203
+ buffer.release();
204
+ }
205
+ }
206
+
207
+ @Override
208
+ public void finish()
209
+ {
210
+ close();
211
+ uploadFile();
212
+ disconnectClient(client);
213
+ }
214
+
215
+ private Void uploadFile()
216
+ {
217
+ if (filePath != null) {
218
+ try {
219
+ return retryExecutor()
220
+ .withRetryLimit(maxConnectionRetry)
221
+ .withInitialRetryWait(500)
222
+ .withMaxRetryWait(30 * 1000)
223
+ .runInterruptible(new Retryable<Void>() {
224
+ @Override
225
+ public Void call() throws FTPIllegalReplyException, FTPException, FTPDataTransferException,
226
+ FTPAbortedException, IOException, RetryGiveupException
227
+ {
228
+ log.info("Upload start {} to {}", file.getAbsolutePath(), filePath);
229
+ client.upload(filePath, new BufferedInputStream(new FileInputStream(file)), 0L, 0L, new LoggingTransferListener(log, TRANSFER_NOTICE_BYTES));
230
+ log.info("Upload completed {} to {}", file.getAbsolutePath(), filePath);
231
+ if (!file.delete()) {
232
+ throw new ConfigException("Couldn't delete local file " + file.getAbsolutePath());
233
+ }
234
+ log.info("Delete local temporary file {}", file.getAbsolutePath());
235
+ return null;
236
+ }
237
+
238
+ @Override
239
+ public boolean isRetryableException(Exception exception)
240
+ {
241
+ return true;
242
+ }
243
+
244
+ @Override
245
+ public void onRetry(Exception exception, int retryCount, int retryLimit, int retryWait)
246
+ throws RetryGiveupException
247
+ {
248
+ if (exception instanceof FileNotFoundException || exception instanceof URISyntaxException || exception instanceof ConfigException) {
249
+ throw new RetryGiveupException(exception);
250
+ }
251
+ String message = String.format("FTP put request failed. Retrying %d/%d after %d seconds. Message: %s",
252
+ retryCount, retryLimit, retryWait / 1000, exception.getMessage());
253
+ if (retryCount % 3 == 0) {
254
+ log.warn(message, exception);
255
+ }
256
+ else {
257
+ log.warn(message);
258
+ }
259
+ }
260
+
261
+ @Override
262
+ public void onGiveup(Exception firstException, Exception lastException)
263
+ throws RetryGiveupException
264
+ {
265
+ }
266
+ });
267
+ }
268
+ catch (RetryGiveupException ex) {
269
+ throw Throwables.propagate(ex.getCause());
270
+ }
271
+ catch (InterruptedException ex) {
272
+ throw Throwables.propagate(ex);
273
+ }
274
+ }
275
+ return null;
276
+ }
277
+
278
+ @Override
279
+ public void close()
280
+ {
281
+ closeFile();
282
+ }
283
+
284
+ @Override
285
+ public void abort() {}
286
+
287
+ @Override
288
+ public TaskReport commit()
289
+ {
290
+ return Exec.newTaskReport();
291
+ }
292
+ }
293
+
294
+ private static FTPClient newFTPClient(Logger log, PluginTask task)
295
+ {
296
+ FTPClient client = new FTPClient();
297
+ try {
298
+ if (task.getSsl()) {
299
+ client.setSSLSocketFactory(SSLPlugins.newSSLSocketFactory(task.getSSLConfig(), task.getHost()));
300
+ client.setSecurity(FTPClient.SECURITY_FTPS);
301
+ if (!task.getPort().isPresent()) {
302
+ task.setPort(Optional.of(990));
303
+ }
304
+ }
305
+ else {
306
+ if (!task.getPort().isPresent()) {
307
+ task.setPort(Optional.of(21));
308
+ }
309
+ }
310
+
311
+ client.addCommunicationListener(new LoggingCommunicationListner(log));
312
+
313
+ // TODO configurable timeout parameters
314
+ client.setAutoNoopTimeout(3000);
315
+
316
+ FTPConnector con = client.getConnector();
317
+ con.setConnectionTimeout(30);
318
+ con.setReadTimeout(60);
319
+ con.setCloseTimeout(60);
320
+
321
+ // for commons-net client
322
+ //client.setControlKeepAliveTimeout
323
+ //client.setConnectTimeout
324
+ //client.setSoTimeout
325
+ //client.setDataTimeout
326
+ //client.setAutodetectUTF8
327
+
328
+ log.info("Connecting to {}", task.getHost());
329
+ if (task.getPort().isPresent()) {
330
+ client.connect(task.getHost(), task.getPort().get());
331
+ }
332
+
333
+ if (task.getUser().isPresent()) {
334
+ log.info("Logging in with user {}", task.getUser().get());
335
+ client.login(task.getUser().get(), task.getPassword().or(""));
336
+ }
337
+
338
+ log.info("Using passive mode");
339
+ client.setPassive(task.getPassiveMode());
340
+
341
+ if (task.getAsciiMode()) {
342
+ log.info("Using ASCII mode");
343
+ client.setType(FTPClient.TYPE_TEXTUAL);
344
+ }
345
+ else {
346
+ log.info("Using binary mode");
347
+ client.setType(FTPClient.TYPE_BINARY);
348
+ }
349
+
350
+ if (client.isCompressionSupported()) {
351
+ log.info("Using MODE Z compression");
352
+ client.setCompressionEnabled(true);
353
+ }
354
+
355
+ FTPClient connected = client;
356
+ client = null;
357
+ return connected;
358
+ }
359
+ catch (FTPException ex) {
360
+ log.info("FTP command failed: {}, {}", ex.getCode(), ex.getMessage());
361
+ throw Throwables.propagate(ex);
362
+ }
363
+ catch (FTPIllegalReplyException ex) {
364
+ log.info("FTP protocol error");
365
+ throw Throwables.propagate(ex);
366
+ }
367
+ catch (IOException ex) {
368
+ log.info("FTP network error: {}", ex);
369
+ throw Throwables.propagate(ex);
370
+ }
371
+ finally {
372
+ disconnectClient(client);
373
+ }
374
+ }
375
+
376
+ static void disconnectClient(FTPClient client)
377
+ {
378
+ if (client != null && client.isConnected()) {
379
+ try {
380
+ client.disconnect(false);
381
+ }
382
+ catch (FTPException | FTPIllegalReplyException | IOException ex) {
383
+ // do nothing
384
+ }
385
+ }
386
+ }
387
+
388
+ private static class LoggingCommunicationListner implements FTPCommunicationListener
389
+ {
390
+ private final Logger log;
391
+
392
+ public LoggingCommunicationListner(Logger log)
393
+ {
394
+ this.log = log;
395
+ }
396
+
397
+ public void received(String statement)
398
+ {
399
+ log.info("< " + statement);
400
+ }
401
+
402
+ public void sent(String statement)
403
+ {
404
+ if (statement.startsWith("PASS")) {
405
+ // don't show password
406
+ return;
407
+ }
408
+ log.info("> {}", statement);
409
+ }
410
+ }
411
+
412
+ private static class LoggingTransferListener implements FTPDataTransferListener
413
+ {
414
+ private final Logger log;
415
+ private final long transferNoticeBytes;
416
+
417
+ private long totalTransfer;
418
+ private long nextTransferNotice;
419
+
420
+ public LoggingTransferListener(Logger log, long transferNoticeBytes)
421
+ {
422
+ this.log = log;
423
+ this.transferNoticeBytes = transferNoticeBytes;
424
+ this.nextTransferNotice = transferNoticeBytes;
425
+ }
426
+
427
+ public void started()
428
+ {
429
+ log.info("Transfer started");
430
+ }
431
+
432
+ public void transferred(int length)
433
+ {
434
+ totalTransfer += length;
435
+ if (totalTransfer > nextTransferNotice) {
436
+ log.info("Transferred {} bytes", totalTransfer);
437
+ nextTransferNotice = ((totalTransfer / transferNoticeBytes) + 1) * transferNoticeBytes;
438
+ }
439
+ }
440
+
441
+ public void completed()
442
+ {
443
+ log.info("Transfer completed {} bytes", totalTransfer);
444
+ }
445
+
446
+ public void aborted()
447
+ {
448
+ log.info("Transfer aborted");
449
+ }
450
+
451
+ public void failed()
452
+ {
453
+ log.info("Transfer failed");
454
+ }
455
+ }
456
+ }
@@ -0,0 +1,260 @@
1
+ package org.embulk.output.ftp;
2
+
3
+ import com.fasterxml.jackson.annotation.JsonCreator;
4
+ import com.fasterxml.jackson.annotation.JsonIgnore;
5
+ import com.fasterxml.jackson.annotation.JsonProperty;
6
+ import com.google.common.base.Function;
7
+ import com.google.common.base.Optional;
8
+ import com.google.common.collect.ImmutableList;
9
+ import com.google.common.collect.Lists;
10
+ import org.embulk.config.Config;
11
+ import org.embulk.config.ConfigDefault;
12
+ import org.embulk.config.ConfigException;
13
+
14
+ import javax.net.ssl.SSLSocketFactory;
15
+ import javax.net.ssl.X509TrustManager;
16
+
17
+ import java.io.ByteArrayInputStream;
18
+ import java.io.FileReader;
19
+ import java.io.IOException;
20
+ import java.io.Reader;
21
+ import java.io.StringReader;
22
+ import java.security.GeneralSecurityException;
23
+ import java.security.KeyManagementException;
24
+ import java.security.cert.CertificateEncodingException;
25
+ import java.security.cert.CertificateException;
26
+ import java.security.cert.CertificateFactory;
27
+ import java.security.cert.X509Certificate;
28
+ import java.util.List;
29
+
30
+ public class SSLPlugins
31
+ {
32
+ // SSLPlugins is only for SSL clients. SSL server implementation is out ouf scope.
33
+
34
+ private SSLPlugins()
35
+ {
36
+ }
37
+
38
+ public interface SSLPluginTask
39
+ {
40
+ @Config("ssl_verify")
41
+ @ConfigDefault("null")
42
+ Optional<Boolean> getSslVerify();
43
+
44
+ @Config("ssl_verify_hostname")
45
+ @ConfigDefault("true")
46
+ boolean getSslVerifyHostname();
47
+
48
+ @Config("ssl_trusted_ca_cert_file")
49
+ @ConfigDefault("null")
50
+ Optional<String> getSslTrustedCaCertFile();
51
+
52
+ @Config("ssl_trusted_ca_cert_data")
53
+ @ConfigDefault("null")
54
+ Optional<String> getSslTrustedCaCertData();
55
+ }
56
+
57
+ private static enum VerifyMode
58
+ {
59
+ NO_VERIFY,
60
+ CERTIFICATES,
61
+ JVM_DEFAULT;
62
+ }
63
+
64
+ public static class SSLPluginConfig
65
+ {
66
+ static SSLPluginConfig noVerify = new SSLPluginConfig(VerifyMode.NO_VERIFY, false, ImmutableList.<byte[]>of());
67
+
68
+ private final VerifyMode verifyMode;
69
+ private final boolean verifyHostname;
70
+ private final List<X509Certificate> certificates;
71
+
72
+ @JsonCreator
73
+ private SSLPluginConfig(
74
+ @JsonProperty("verifyMode") VerifyMode verifyMode,
75
+ @JsonProperty("verifyHostname") boolean verifyHostname,
76
+ @JsonProperty("certificates") List<byte[]> certificates)
77
+ {
78
+ this.verifyMode = verifyMode;
79
+ this.verifyHostname = verifyHostname;
80
+ this.certificates = ImmutableList.copyOf(
81
+ Lists.transform(certificates, new Function<byte[], X509Certificate>() {
82
+ public X509Certificate apply(byte[] data)
83
+ {
84
+ try (ByteArrayInputStream in = new ByteArrayInputStream(data)) {
85
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
86
+ return (X509Certificate) cf.generateCertificate(in);
87
+ }
88
+ catch (IOException | CertificateException ex) {
89
+ throw new RuntimeException(ex);
90
+ }
91
+ }
92
+ })
93
+ );
94
+ }
95
+
96
+ SSLPluginConfig(List<X509Certificate> certificates, boolean verifyHostname)
97
+ {
98
+ this.verifyMode = VerifyMode.CERTIFICATES;
99
+ this.verifyHostname = verifyHostname;
100
+ this.certificates = certificates;
101
+ }
102
+
103
+ static SSLPluginConfig useJvmDefault(boolean verifyHostname)
104
+ {
105
+ return new SSLPluginConfig(VerifyMode.JVM_DEFAULT, verifyHostname, ImmutableList.<byte[]>of());
106
+ }
107
+
108
+ @JsonProperty("verifyMode")
109
+ private VerifyMode getVerifyMode()
110
+ {
111
+ return verifyMode;
112
+ }
113
+
114
+ @JsonProperty("verifyHostname")
115
+ private boolean getVerifyHostname()
116
+ {
117
+ return verifyHostname;
118
+ }
119
+
120
+ @JsonProperty("certificates")
121
+ private List<byte[]> getCertData()
122
+ {
123
+ return Lists.transform(certificates, new Function<X509Certificate, byte[]>() {
124
+ public byte[] apply(X509Certificate cert)
125
+ {
126
+ try {
127
+ return cert.getEncoded();
128
+ }
129
+ catch (CertificateEncodingException ex) {
130
+ throw new RuntimeException(ex);
131
+ }
132
+ }
133
+ });
134
+ }
135
+
136
+ @JsonIgnore
137
+ public X509TrustManager[] newTrustManager()
138
+ {
139
+ try {
140
+ switch (verifyMode) {
141
+ case NO_VERIFY:
142
+ return new X509TrustManager[] { getNoVerifyTrustManager() };
143
+ case CERTIFICATES:
144
+ return TrustManagers.newTrustManager(certificates);
145
+ default: // JVM_DEFAULT
146
+ return TrustManagers.newDefaultJavaTrustManager();
147
+ }
148
+ }
149
+ catch (IOException | GeneralSecurityException ex) {
150
+ throw new RuntimeException(ex);
151
+ }
152
+ }
153
+ }
154
+
155
+ public static enum DefaultVerifyMode
156
+ {
157
+ VERIFY_BY_JVM_TRUSTED_CA_CERTS,
158
+ NO_VERIFY;
159
+ }
160
+
161
+ public static SSLPluginConfig configure(SSLPluginTask task)
162
+ {
163
+ return configure(task, DefaultVerifyMode.VERIFY_BY_JVM_TRUSTED_CA_CERTS);
164
+ }
165
+
166
+ public static SSLPluginConfig configure(SSLPluginTask task, DefaultVerifyMode defaultVerifyMode)
167
+ {
168
+ boolean verify = task.getSslVerify().or(defaultVerifyMode != DefaultVerifyMode.NO_VERIFY);
169
+ if (verify) {
170
+ Optional<List<X509Certificate>> certs = readTrustedCertificates(task);
171
+ if (certs.isPresent()) {
172
+ return new SSLPluginConfig(certs.get(), task.getSslVerifyHostname());
173
+ }
174
+ else {
175
+ return SSLPluginConfig.useJvmDefault(task.getSslVerifyHostname());
176
+ }
177
+ }
178
+ else {
179
+ return SSLPluginConfig.noVerify;
180
+ }
181
+ }
182
+
183
+ private static Optional<List<X509Certificate>> readTrustedCertificates(SSLPluginTask task)
184
+ {
185
+ String optionName;
186
+ Reader reader;
187
+ if (task.getSslTrustedCaCertData().isPresent()) {
188
+ optionName = "ssl_trusted_ca_cert_data";
189
+ reader = new StringReader(task.getSslTrustedCaCertData().get());
190
+ }
191
+ else if (task.getSslTrustedCaCertFile().isPresent()) {
192
+ optionName = "ssl_trusted_ca_cert_file '" + task.getSslTrustedCaCertFile().get() + "'";
193
+ try {
194
+ reader = new FileReader(task.getSslTrustedCaCertFile().get());
195
+ }
196
+ catch (IOException ex) {
197
+ throw new ConfigException(String.format("Failed to open %s", optionName), ex);
198
+ }
199
+ }
200
+ else {
201
+ return Optional.absent();
202
+ }
203
+
204
+ List<X509Certificate> certs;
205
+ try (Reader r = reader) {
206
+ certs = TrustManagers.readPemEncodedX509Certificates(r);
207
+ if (certs.isEmpty()) {
208
+ throw new ConfigException(String.format("%s does not include valid X.509 PEM certificates", optionName));
209
+ }
210
+ }
211
+ catch (CertificateException | IOException ex) {
212
+ throw new ConfigException(String.format("Failed to read %s", optionName), ex);
213
+ }
214
+
215
+ return Optional.of(certs);
216
+ }
217
+
218
+ public static SSLSocketFactory newSSLSocketFactory(SSLPluginConfig config, String hostname)
219
+ {
220
+ try {
221
+ return TrustManagers.newSSLSocketFactory(
222
+ null, // TODO sending client certificate is not implemented yet
223
+ config.newTrustManager(),
224
+ config.getVerifyHostname() ? hostname : null);
225
+ }
226
+ catch (KeyManagementException ex) {
227
+ throw new RuntimeException(ex);
228
+ }
229
+ }
230
+
231
+ private static class NoVerifyTrustManager implements X509TrustManager
232
+ {
233
+ static final NoVerifyTrustManager INSTANCE = new NoVerifyTrustManager();
234
+
235
+ private NoVerifyTrustManager()
236
+ {
237
+ }
238
+
239
+ @Override
240
+ public X509Certificate[] getAcceptedIssuers()
241
+ {
242
+ return null;
243
+ }
244
+
245
+ @Override
246
+ public void checkClientTrusted(X509Certificate[] certs, String authType)
247
+ {
248
+ }
249
+
250
+ @Override
251
+ public void checkServerTrusted(X509Certificate[] certs, String authType)
252
+ {
253
+ }
254
+ }
255
+
256
+ private static X509TrustManager getNoVerifyTrustManager()
257
+ {
258
+ return NoVerifyTrustManager.INSTANCE;
259
+ }
260
+ }