This closes Improved FTP 550 file unavailable handling
Improved File Not Found reply detection
Added Permission Denied reply handling
@@ -135,6 +135,10 @@ public class FTPTransfer implements FileTransfer {
.addValidator(StandardValidators.BOOLEAN_VALIDATOR)
.build();
+ private static final int REPLY_CODE_FILE_UNAVAILABLE = 550;
+
+ private static final Pattern NOT_FOUND_MESSAGE_PATTERN = Pattern.compile("(no such)|(not exist)|(not found)", Pattern.CASE_INSENSITIVE);
+
private static final FTPClientProvider FTP_CLIENT_PROVIDER = new StandardFTPClientProvider();
private static final ProxySpec[] PROXY_SPECS = {ProxySpec.HTTP_AUTH, ProxySpec.SOCKS_AUTH};
@@ -321,13 +325,22 @@ public class FTPTransfer implements FileTransfer {
FlowFile resultFlowFile;
try (InputStream in = client.retrieveFileStream(remoteFileName)) {
if (in == null) {
- final String response = client.getReplyString();
- // FTPClient doesn't throw exception if file not found.
- // Instead, response string will contain: "550 Can't open <absolute_path>: No such file or directory"
- if (response != null && response.trim().endsWith("No such file or directory")) {
- throw new FileNotFoundException(response);
+ final String reply = client.getReplyString();
+ if (reply == null) {
+ throw new IOException("Retrieve File Failed: FTP server response not found");
+ }
+
+ // Get reply code after checking for reply string
+ final int replyCode = client.getReplyCode();
+ if (REPLY_CODE_FILE_UNAVAILABLE == replyCode) {
+ if (NOT_FOUND_MESSAGE_PATTERN.matcher(reply).find()) {
+ throw new FileNotFoundException(reply);
+ } else {
+ throw new PermissionDeniedException(reply);
+ }
}
- throw new IOException(response);
+
+ throw new IOException(reply);
}
resultFlowFile = session.write(origFlowFile, out -> StreamUtils.copy(in, out));
client.completePendingCommand();
@@ -606,5 +619,4 @@ public class FTPTransfer implements FileTransfer {
return componentProxyConfig;
};
}
-
}
