public void execute()

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
                }
            }
        }
    }