| @@ -25,6 +25,7 @@ import java.io.FileWriter; | |||||
| import java.io.IOException; | import java.io.IOException; | ||||
| import java.io.InputStream; | import java.io.InputStream; | ||||
| import java.io.OutputStream; | import java.io.OutputStream; | ||||
| import java.net.SocketTimeoutException; | |||||
| import java.nio.file.Files; | import java.nio.file.Files; | ||||
| import java.text.SimpleDateFormat; | import java.text.SimpleDateFormat; | ||||
| import java.util.Collection; | import java.util.Collection; | ||||
| @@ -144,6 +145,7 @@ public class FTP extends Task implements FTPTaskConfig { | |||||
| private String siteCommand = null; | private String siteCommand = null; | ||||
| private String initialSiteCommand = null; | private String initialSiteCommand = null; | ||||
| private boolean enableRemoteVerification = true; | private boolean enableRemoteVerification = true; | ||||
| private int dataTimeout = -1; | |||||
| protected static final String[] ACTION_STRS = { //NOSONAR | protected static final String[] ACTION_STRS = { //NOSONAR | ||||
| "sending", | "sending", | ||||
| @@ -1694,6 +1696,19 @@ public class FTP extends Task implements FTPTaskConfig { | |||||
| enableRemoteVerification = b; | enableRemoteVerification = b; | ||||
| } | } | ||||
| /** | |||||
| * Sets the timeout on the data connection. | |||||
| * Any negative value is discarded and leaves the default | |||||
| * | |||||
| * @param dataTimeout int | |||||
| * @since Ant 1.10.6 | |||||
| */ | |||||
| public void setDataTimeout(int dataTimeout) { | |||||
| if(dataTimeout >= 0) { | |||||
| this.dataTimeout = dataTimeout; | |||||
| } | |||||
| } | |||||
| /** | /** | ||||
| * Checks to see that all required parameters are set. | * Checks to see that all required parameters are set. | ||||
| * | * | ||||
| @@ -2443,6 +2458,11 @@ public class FTP extends Task implements FTPTaskConfig { | |||||
| ftp.setRemoteVerificationEnabled(enableRemoteVerification); | ftp.setRemoteVerificationEnabled(enableRemoteVerification); | ||||
| ftp.connect(server, port); | ftp.connect(server, port); | ||||
| if (dataTimeout >= 0) { | |||||
| ftp.setDataTimeout(dataTimeout); | |||||
| log("Setting data timeout to " + dataTimeout, Project.MSG_VERBOSE); | |||||
| } | |||||
| if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) { | if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) { | ||||
| throw new BuildException("FTP connection failed: %s", | throw new BuildException("FTP connection failed: %s", | ||||
| ftp.getReplyString()); | ftp.getReplyString()); | ||||
| @@ -2536,6 +2556,22 @@ public class FTP extends Task implements FTPTaskConfig { | |||||
| } | } | ||||
| } catch (IOException ex) { | } catch (IOException ex) { | ||||
| String cause = ex.getCause().toString(); | |||||
| if(cause != null) { | |||||
| if(cause.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 doesn't | |||||
| // 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); | throw new BuildException("error during FTP transfer: " + ex, ex); | ||||
| } finally { | } finally { | ||||
| if (ftp != null && ftp.isConnected()) { | if (ftp != null && ftp.isConnected()) { | ||||