Skip to content

Commit e4a511c

Browse files
authored
Merge pull request #45 from data-integrations/username-colon
PLUGIN-1181 added timeout field.
2 parents 1f8c89d + 3ae98ba commit e4a511c

File tree

6 files changed

+53
-11
lines changed

6 files changed

+53
-11
lines changed

docs/FTPSource-batchsource.md

+5-3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Properties
2323

2424
**Path:** Path to the file or directory to read from. For example: /path/to/directory.
2525

26-
**User:** User name to use for authentication.
26+
**User:** Username to use for authentication.
2727

2828
**Password:** Password to use for authentication.
2929

@@ -68,6 +68,8 @@ complete
6868
path and returns the list of files that match the specified pattern.
6969

7070
**Allow Empty Input:** Identify if path needs to be ignored or not, for case when directory or file does not
71-
exists. If set to true it will treat the not present folder as 0 input and log a warning. Default is false.
71+
exist. If set to true it will treat the not present folder as 0 input and log a warning. Default is false.
7272

73-
**File System Properties:** Additional properties to use with the InputFormat when reading the data.
73+
**File System Properties:** Additional properties to use with the InputFormat when reading the data.
74+
75+
**Connect Timeout:** Maximum time in milliseconds to wait for connection initialization before it times out.

src/main/java/io/cdap/plugin/batch/source/ftp/FTPConfig.java

+23-4
Original file line numberDiff line numberDiff line change
@@ -145,13 +145,18 @@ public class FTPConfig extends PluginConfig implements FileSourceProperties {
145145
"value will only be used if the format is 'csv', 'tsv' or 'delimited'. The default value is false.")
146146
protected Boolean enableMultilineSupport;
147147

148+
@Macro
149+
@Nullable
150+
@Description("Maximum time in milliseconds to wait for connection initialization before time out.")
151+
private final Integer connectTimeout;
152+
148153
@VisibleForTesting
149154
private FTPConfig(@Nullable String referenceName, String type, String host, @Nullable Integer port, String path,
150155
String user, String password, @Nullable String fileSystemProperties,
151156
@Nullable Boolean ignoreNonExistingFolders, @Nullable String fileRegex,
152157
@Nullable Boolean skipHeader, @Nullable String format, @Nullable String schema,
153158
@Nullable String delimiter, @Nullable Boolean enableQuotedValues,
154-
@Nullable Boolean enableMultilineSupport) {
159+
@Nullable Boolean enableMultilineSupport, @Nullable Integer connectTimeout) {
155160
this.referenceName = referenceName;
156161
this.type = type;
157162
this.host = host;
@@ -168,6 +173,14 @@ private FTPConfig(@Nullable String referenceName, String type, String host, @Nul
168173
this.delimiter = delimiter;
169174
this.enableQuotedValues = enableQuotedValues;
170175
this.enableMultilineSupport = enableMultilineSupport;
176+
this.connectTimeout = connectTimeout;
177+
}
178+
179+
public int getConnectTimeout() {
180+
if (connectTimeout == null) {
181+
return FTPFileSystem.DEFAULT_CONNECTION_TIMEOUT_MS;
182+
}
183+
return connectTimeout;
171184
}
172185

173186
@Override
@@ -186,10 +199,9 @@ public void validate(FailureCollector collector) {
186199
for (Map.Entry<String, String> entry : location.getHadoopProperties().entrySet()) {
187200
conf.set(entry.getKey(), entry.getValue());
188201
}
202+
conf.setInt(FTPFileSystem.FS_CONNECT_TIMEOUT, getConnectTimeout());
189203
try (FileSystem fs = JobUtils.applyWithExtraClassLoader(job, getClass().getClassLoader(),
190204
f -> FileSystem.get(location.getURI(), conf))) {
191-
// TODO: Add setTimeout option in the future
192-
// https://cdap.atlassian.net/browse/PLUGIN-1181
193205
fs.getFileStatus(new Path(location.getURI()));
194206
}
195207
} catch (Exception e) {
@@ -371,6 +383,7 @@ static class Builder {
371383
private boolean skipHeader;
372384
private boolean enableQuotedValues;
373385
private boolean enableMultilineSupport;
386+
private Integer connectTimeout;
374387

375388
Builder() {
376389
this.fileSystemProperties = new HashMap<>();
@@ -379,6 +392,7 @@ static class Builder {
379392
this.enableMultilineSupport = false;
380393
this.skipHeader = false;
381394
this.format = "text";
395+
this.connectTimeout = FTPFileSystem.DEFAULT_CONNECTION_TIMEOUT_MS;
382396
}
383397

384398
Builder setType(FTPLocation.Type type) {
@@ -462,11 +476,16 @@ Builder setEnableMultilineSupport(boolean enableMultilineSupport) {
462476
return this;
463477
}
464478

479+
Builder setConnectTimeout(Integer connectTimeout) {
480+
this.connectTimeout = connectTimeout;
481+
return this;
482+
}
483+
465484
FTPConfig build() {
466485
return new FTPConfig(referenceName, type.name(), host, port, path, user, password,
467486
GSON.toJson(fileSystemProperties), ignoreNonExistingFolders, fileRegex, skipHeader,
468487
format, schema == null ? null : schema.toString(), delimiter, enableQuotedValues,
469-
enableMultilineSupport);
488+
enableMultilineSupport, connectTimeout);
470489
}
471490
}
472491
}

src/main/java/io/cdap/plugin/batch/source/ftp/FTPFileSystem.java

+6
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ public class FTPFileSystem extends FileSystem {
5353

5454
public static final int DEFAULT_BLOCK_SIZE = 4 * 1024;
5555

56+
public static final Integer DEFAULT_CONNECTION_TIMEOUT_MS = 30000;
57+
58+
public static final String FS_CONNECT_TIMEOUT = "fs.connect.timeout";
59+
5660
private URI uri;
5761

5862
/**
@@ -111,7 +115,9 @@ private FTPClient connect() throws IOException {
111115
int port = conf.getInt("fs.ftp.host.port", FTP.DEFAULT_PORT);
112116
String user = conf.get("fs.ftp.user." + host);
113117
String password = conf.get("fs.ftp.password." + host);
118+
int connectTimeout = conf.getInt(FS_CONNECT_TIMEOUT, DEFAULT_CONNECTION_TIMEOUT_MS);
114119
client = new FTPClient();
120+
client.setConnectTimeout(connectTimeout);
115121
client.connect(host, port);
116122
int reply = client.getReplyCode();
117123
if (!FTPReply.isPositiveCompletion(reply)) {

src/main/java/io/cdap/plugin/batch/source/ftp/SFTPConnectionPool.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.apache.hadoop.util.StringUtils;
2525
import org.slf4j.Logger;
2626
import org.slf4j.LoggerFactory;
27+
2728
import java.io.IOException;
2829
import java.util.HashMap;
2930
import java.util.HashSet;
@@ -118,7 +119,7 @@ public synchronized void setMaxConnection(int maxConn) {
118119
}
119120

120121
public ChannelSftp connect(String host, int port, String user,
121-
String password, String keyFile) throws IOException {
122+
String password, String keyFile, int timeout) throws IOException {
122123
// get connection from pool
123124
ConnectionInfo info = new ConnectionInfo(host, port, user);
124125
ChannelSftp channel = getFromPool(info);
@@ -161,6 +162,7 @@ public ChannelSftp connect(String host, int port, String user,
161162

162163
java.util.Properties config = new java.util.Properties();
163164
config.put("StrictHostKeyChecking", "no");
165+
config.put("ConnectTimeout", String.valueOf(timeout));
164166
session.setConfig(config);
165167

166168
session.connect();

src/main/java/io/cdap/plugin/batch/source/ftp/SFTPFileSystem.java

+7-3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.apache.hadoop.fs.Path;
3030
import org.apache.hadoop.fs.permission.FsPermission;
3131
import org.apache.hadoop.util.Progressable;
32+
3233
import java.io.FileNotFoundException;
3334
import java.io.IOException;
3435
import java.io.InputStream;
@@ -83,11 +84,13 @@ public class SFTPFileSystem extends FileSystem {
8384
"Destination path %s already exist, cannot rename!";
8485
public static final String E_FAILED_GETHOME = "Failed to get home directory";
8586
public static final String E_FAILED_DISCONNECT = "Failed to disconnect";
87+
public static final Integer DEFAULT_CONNECTION_TIMEOUT_MS = 30000;
88+
public static final String FS_CONNECT_TIMEOUT = "fs.connect.timeout";
8689

8790
/**
8891
* Set configuration from UI.
8992
*
90-
* @param uri
93+
* @param uriInfo
9194
* @param conf
9295
* @throws IOException
9396
*/
@@ -145,17 +148,18 @@ private ChannelSftp connect() throws IOException {
145148
String user = conf.get(FS_SFTP_USER_PREFIX + host, null);
146149
String pwd = conf.get(FS_SFTP_PASSWORD_PREFIX + host + "." + user, null);
147150
String keyFile = conf.get(FS_SFTP_KEYFILE, null);
151+
int connectTimeout = conf.getInt(FS_CONNECT_TIMEOUT, DEFAULT_CONNECTION_TIMEOUT_MS);
148152

149153
ChannelSftp channel =
150-
connectionPool.connect(host, port, user, pwd, keyFile);
154+
connectionPool.connect(host, port, user, pwd, keyFile, connectTimeout);
151155

152156
return channel;
153157
}
154158

155159
/**
156160
* Logout and disconnect the given channel.
157161
*
158-
* @param client
162+
* @param channel
159163
* @throws IOException
160164
*/
161165
private void disconnect(ChannelSftp channel) throws IOException {

widgets/FTPSource-batchsource.json

+9
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,15 @@
185185
}
186186
]
187187
}
188+
},
189+
{
190+
"widget-type": "number",
191+
"label": "Connect Timeout (milliseconds)",
192+
"name": "connectTimeout",
193+
"widget-attributes": {
194+
"min": "0",
195+
"default": "30000"
196+
}
188197
}
189198
]
190199
}

0 commit comments

Comments
 (0)