in src/main/org/apache/tools/ant/taskdefs/optional/net/FTP.java [2525:2687]
public void execute() throws BuildException {
checkAttributes();
FTPClient ftp = null;
try {
if (useFtps) {
log("Opening FTPs connection to " + server, Project.MSG_VERBOSE);
FTPSClient ftps = new FTPSClient();
ftps.setEndpointCheckingEnabled(true);
if (hostnameVerifier != null) {
ftps.setHostnameVerifier(hostnameVerifier);
}
ftp = ftps;
} else {
log("Opening FTP connection to " + server, Project.MSG_VERBOSE);
ftp = new FTPClient();
}
if (this.isConfigurationSet) {
ftp = FTPConfigurator.configure(ftp, this);
}
ftp.setRemoteVerificationEnabled(enableRemoteVerification);
ftp.connect(server, port);
if (dataTimeout >= 0) {
ftp.setDataTimeout(dataTimeout);
log("Setting data timeout to " + dataTimeout, Project.MSG_VERBOSE);
}
if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
throw new BuildException("FTP connection failed: %s",
ftp.getReplyString());
}
log("connected", Project.MSG_VERBOSE);
log("logging in to FTP server", Project.MSG_VERBOSE);
if ((this.account != null && !ftp.login(userid, password, account))
|| (this.account == null && !ftp.login(userid, password))) {
throw new BuildException("Could not login to FTP server");
}
log("login succeeded", Project.MSG_VERBOSE);
if (binary) {
ftp.setFileType(org.apache.commons.net.ftp.FTP.BINARY_FILE_TYPE);
} else {
ftp.setFileType(org.apache.commons.net.ftp.FTP.ASCII_FILE_TYPE);
}
if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
throw new BuildException("could not set transfer type: %s",
ftp.getReplyString());
}
if (passive) {
log("entering passive mode", Project.MSG_VERBOSE);
ftp.enterLocalPassiveMode();
if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
throw new BuildException(
"could not enter into passive mode: %s",
ftp.getReplyString());
}
}
// if it is FTPS and secure data channel is desired, then we exec "PROT P"
// command to enable secure data channel, for the lifetime of this client
if (useFtps && useSecureDataChannel) {
FTPSClient ftps = (FTPSClient) ftp;
try {
// first issue a PBSZ command as mandated by RFC-2228.
// we set 0 because the buffer size is redundant since the encryption
// is handled at TLS layer and not application layer
ftps.execPBSZ(0);
ftps.execPROT("P"); // P implies PRIVATE and enables encryption
} catch (IOException e) {
throw new BuildException("failed to enable secure data channel: " + e, e);
}
log("enabled secure data channel", Project.MSG_VERBOSE);
}
// If an initial command was configured then send it.
// Some FTP servers offer different modes of operation,
// E.G. switching between a UNIX file system mode and
// a legacy file system.
if (this.initialSiteCommand != null) {
final FTPClient lftp = ftp;
executeRetryable(new RetryHandler(this.retriesAllowed, this),
() -> doSiteCommand(lftp, FTP.this.initialSiteCommand),
"initial site command: " + this.initialSiteCommand);
}
// For a unix ftp server you can set the default mask for all files
// created.
if (umask != null) {
final FTPClient lftp = ftp;
executeRetryable(new RetryHandler(this.retriesAllowed, this),
() -> doSiteCommand(lftp, "umask " + umask),
"umask " + umask);
}
// If the action is MK_DIR, then the specified remote
// directory is the directory to create.
if (action == MK_DIR) {
final FTPClient lftp = ftp;
executeRetryable(new RetryHandler(this.retriesAllowed, this),
() -> makeRemoteDir(lftp, remotedir), remotedir);
} else if (action == SITE_CMD) {
final FTPClient lftp = ftp;
executeRetryable(new RetryHandler(this.retriesAllowed, this),
() -> doSiteCommand(lftp, FTP.this.siteCommand),
"Site Command: " + this.siteCommand);
} else {
if (remotedir != null) {
log("changing the remote directory to " + remotedir,
Project.MSG_VERBOSE);
ftp.changeWorkingDirectory(remotedir);
if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
throw new BuildException(
"could not change remote directory: %s",
ftp.getReplyString());
}
}
if (newerOnly && timeDiffAuto) {
// in this case we want to find how much time span there is between local
// and remote
timeDiffMillis = getTimeDiff(ftp);
}
log(ACTION_STRS[action] + " " + ACTION_TARGET_STRS[action]);
transferFiles(ftp);
}
} catch (IOException ex) {
final Throwable cause = ex.getCause();
if (cause != null) {
final String msg = cause.toString();
if (msg != null && msg.contains("java.net.SocketTimeoutException")) {
// When a read timeout occurs, inform the server that it
// should abort.
// Note that the latest commons-net (3.6) still does not
// support sending urgent data, which is normally a
// prerequisite for ABORT command.
// As a consequence, it might not be taken in account immediately
try {
ftp.abort();
} catch (IOException ioe) {
// ignore it
}
}
}
throw new BuildException("error during FTP transfer: " + ex, ex);
} finally {
if (ftp != null && ftp.isConnected()) {
try {
log("disconnecting", Project.MSG_VERBOSE);
ftp.logout();
ftp.disconnect();
} catch (IOException ex) {
// ignore it
}
}
}
}