diff --git a/src/etc/testcases/taskdefs/optional/net/ftp.xml b/src/etc/testcases/taskdefs/optional/net/ftp.xml index 5603ce7a8..2fb6e3ca2 100644 --- a/src/etc/testcases/taskdefs/optional/net/ftp.xml +++ b/src/etc/testcases/taskdefs/optional/net/ftp.xml @@ -14,6 +14,7 @@ + @@ -191,5 +192,59 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/net/FTP.java b/src/main/org/apache/tools/ant/taskdefs/optional/net/FTP.java index 68bca232d..ed8ab4f0d 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/net/FTP.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/net/FTP.java @@ -101,6 +101,7 @@ public class FTP private boolean verbose = false; private boolean newerOnly = false; private long timeDiffMillis = 0; + private long granularityMillis = 0L; private boolean timeDiffAuto = false; private int action = SEND_FILES; private Vector filesets = new Vector(); @@ -114,14 +115,13 @@ public class FTP private boolean preserveLastModified = false; private String chmod = null; private String umask = null; - private String systemTypeKey = null; + private FTPSystemType systemTypeKey = FTPSystemType.getDefault(); private String defaultDateFormatConfig = null; private String recentDateFormatConfig = null; private String serverLanguageCodeConfig = null; private String serverTimeZoneConfig = null; private String shortMonthNamesConfig = null; - private String timestampGranularity = null; - private long serverTimestampGranularity = 0L; + private Granularity timestampGranularity = Granularity.getDefault(); private boolean isConfigurationSet = false; protected static final String[] ACTION_STRS = { @@ -1268,8 +1268,8 @@ public class FTP * the default value of null will be kept. * @see org.apache.commons.net.ftp.FTPClientConfig */ - public void setSystemTypeKey(String systemKey) { - if (systemKey != null && !systemKey.equals("")) + public void setSystemTypeKey(FTPSystemType systemKey) { + if (systemKey != null && !systemKey.getValue().equals("")) { this.systemTypeKey = systemKey; configurationHasBeenSet(); @@ -1361,7 +1361,7 @@ public class FTP * @return Returns the systemTypeKey. */ String getSystemTypeKey() { - return systemTypeKey; + return systemTypeKey.getValue(); } /** * @return Returns the defaultDateFormatConfig. @@ -1396,13 +1396,13 @@ public class FTP /** * @return Returns the timestampGranularity. */ - String getTimestampGranularity() { + Granularity getTimestampGranularity() { return timestampGranularity; } /** * @param timestampGranularity The timestampGranularity to set. */ - public void setTimestampGranularity(String timestampGranularity) { + public void setTimestampGranularity(Granularity timestampGranularity) { if (null == timestampGranularity || "".equals(timestampGranularity)) { return; } @@ -1517,29 +1517,8 @@ public class FTP } } else { if (this.newerOnly) { - if (action == SEND_FILES) { - if ("NONE".equalsIgnoreCase(this.timestampGranularity)) - { - this.serverTimestampGranularity = 0L; - } - else if ("MINUTE".equalsIgnoreCase(this.timestampGranularity)) - { - this.serverTimestampGranularity = GRANULARITY_MINUTE; - } - else - { - this.serverTimestampGranularity = GRANULARITY_MINUTE; - } - } else if (action == GET_FILES) { - if ("MINUTE".equalsIgnoreCase(this.timestampGranularity)) - { - this.serverTimestampGranularity = GRANULARITY_MINUTE; - } - else - { - this.serverTimestampGranularity = 0L; - } - } + this.granularityMillis = + this.timestampGranularity.getMilliseconds(action); } for (int i = 0; i < dsfiles.length; i++) { switch (action) { @@ -1799,13 +1778,13 @@ public class FTP if (this.action == SEND_FILES) { return remoteTimestamp + this.timeDiffMillis - + this.serverTimestampGranularity + + this.granularityMillis >= localTimestamp; } else { return localTimestamp >= remoteTimestamp + this.timeDiffMillis - + this.serverTimestampGranularity; + + this.granularityMillis; } } @@ -2300,5 +2279,84 @@ public class FTP return SEND_FILES; } } + /** + * represents one of the valid timestamp adjustment values + * recognized by the timestampGranularity attribute.

+ + * A timestamp adjustment may be used in file transfers for checking + * uptodateness. MINUTE means to add one minute to the server + * timestamp. This is done because FTP servers typically list + * timestamps HH:mm and client FileSystems typically use HH:mm:ss. + * + * The default is to use MINUTE for PUT actions and NONE for GET + * actions, since GETs have the preserveLastModified + * option, which takes care of the problem in most use cases where + * this level of granularity is an issue. + * + */ + public static class Granularity extends EnumeratedAttribute { + + private static final String[] VALID_GRANULARITIES = { + "", "MINUTE", "NONE" + }; + /* + * @return the list of valid Granularity values + */ + public String[] getValues() { + // TODO Auto-generated method stub + return VALID_GRANULARITIES; + } + /** + * returns the number of milliseconds associated with + * the attribute, which can vary in some cases depending + * on the value of the action parameter. + * @param action SEND_FILES or GET_FILES + * @return the number of milliseconds associated with + * the attribute, in the context of the supplied action + */ + public long getMilliseconds(int action) { + String granularityU = getValue().toUpperCase(Locale.US); + long granularity = 0L; + if ("".equals(granularityU)) { + if (action == SEND_FILES) { + return GRANULARITY_MINUTE; + } + } else if ("MINUTE".equals(granularityU)) { + return GRANULARITY_MINUTE; + } + return 0L; + } + static final Granularity getDefault() { + Granularity g = new Granularity(); + g.setValue(""); + return g; + } + + } + /** + * one of the valid system type keys recognized by the systemTypeKey + * attribute. + */ + public static class FTPSystemType extends EnumeratedAttribute { + + private static final String[] VALID_SYSTEM_TYPES = { + "", "UNIX", "VMS", "WINDOWS", "OS/2", "OS/400", + "MVS" + }; + + + /* + * @return the list of valid system types. + */ + public String[] getValues() { + return VALID_SYSTEM_TYPES; + } + + static final FTPSystemType getDefault() { + FTPSystemType ftpst = new FTPSystemType(); + ftpst.setValue(""); + return ftpst; + } + } } diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPConfigurator.java b/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPConfigurator.java index 6fda45f1c..aafda1a02 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPConfigurator.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/net/FTPConfigurator.java @@ -37,14 +37,17 @@ class FTPConfigurator { * @return the client as configured. */ static FTPClient configure(FTPClient client, FTP task) { + task.log("custom configuration", Project.MSG_VERBOSE); FTPClientConfig config; String systemTypeKey = task.getSystemTypeKey(); - if (systemTypeKey != null) { + if (systemTypeKey != null && !"".equals(systemTypeKey)) { config = new FTPClientConfig(systemTypeKey); task.log("custom config: system key = " + systemTypeKey, Project.MSG_VERBOSE); } else { config = new FTPClientConfig(); + task.log("custom config: system key = default (UNIX)", + Project.MSG_VERBOSE); } String defaultDateFormatConfig = task.getDefaultDateFormatConfig(); diff --git a/src/testcases/org/apache/tools/ant/taskdefs/optional/net/FTPTest.java b/src/testcases/org/apache/tools/ant/taskdefs/optional/net/FTPTest.java index fdef6b3be..9f9636ad9 100644 --- a/src/testcases/org/apache/tools/ant/taskdefs/optional/net/FTPTest.java +++ b/src/testcases/org/apache/tools/ant/taskdefs/optional/net/FTPTest.java @@ -16,25 +16,23 @@ */ package org.apache.tools.ant.taskdefs.optional.net; +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Vector; + +import org.apache.commons.net.ftp.FTPClient; import org.apache.tools.ant.BuildEvent; import org.apache.tools.ant.BuildFileTest; -import org.apache.tools.ant.BuildListener; -import org.apache.tools.ant.BuildLogger; import org.apache.tools.ant.DefaultLogger; import org.apache.tools.ant.DirectoryScanner; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.taskdefs.condition.Os; import org.apache.tools.ant.types.FileSet; -import org.apache.tools.ant.taskdefs.optional.net.FTP; -import org.apache.tools.ant.util.JavaEnvUtils; import org.apache.tools.ant.util.regexp.RegexpMatcher; import org.apache.tools.ant.util.regexp.RegexpMatcherFactory; -import org.apache.tools.ant.taskdefs.condition.Os; - -import java.io.File; -import java.io.IOException; -import java.util.Arrays; -import java.util.Vector; - -import org.apache.commons.net.ftp.FTPClient; public class FTPTest extends BuildFileTest{ // keep track of what operating systems are supported here. @@ -592,6 +590,42 @@ public class FTPTest extends BuildFileTest{ } } + /** + * This class enables the use of the log to count the number + * of times a message has been emitted. + */ + private class LogCounter extends DefaultLogger { + private Map searchMap = new HashMap(); + private int matchCount; + + public void addLogMessageToSearch(String message) { + searchMap.put(message, new Integer(0)); + } + + /* + * @param event the build event that is being logged. + */ + public void messageLogged(BuildEvent event) { + String message = event.getMessage(); + Integer mcnt = (Integer) searchMap.get(message); + if (null != mcnt) { + searchMap.put(message, new Integer(mcnt.intValue() + 1)); + } + super.messageLogged(event); + } + + /** + * @return the number of times that the looked for message was sent + * to the log + */ + public int getMatchCount(String message) { + Integer mcnt = (Integer) searchMap.get(message); + if (null != mcnt) { + return mcnt.intValue(); + } + return 0; + } + } /** * Tests the combination of the newer parameter and the * serverTimezoneConfig parameter in the PUT action. The default @@ -619,7 +653,76 @@ public class FTPTest extends BuildFileTest{ getProject().executeTarget("timed.test.get.older"); assertEquals(3, log.getCount()); } + + + /** + * Tests that the presence of one of the server config params forces + * the system type to Unix if not specified. + */ + public void testConfiguration1() { + int[] expectedCounts = { + 1,1,0,1,0,0 + }; + performConfigTest("configuration.1", expectedCounts); + + } + /** + * Tests the systemTypeKey attribute. + */ + public void testConfiguration2() { + int[] expectedCounts = { + 1,0,0,1,1,0 + }; + performConfigTest("configuration.2", expectedCounts); + + } + + /** + * Tests the systemTypeKey attribute with UNIX specified. + */ + public void testConfiguration3() { + int[] expectedCounts = { + 1,0,1,0,0,1 + }; + performConfigTest("configuration.3", expectedCounts); + + } + /** + * Tests the systemTypeKey attribute. + */ + public void testConfigurationNone() { + int[] expectedCounts = { + 0,0,0,0,0,0 + }; + performConfigTest("configuration.none", expectedCounts); + + } + + private void performConfigTest(String target, int[] expectedCounts) { + String[] messages = new String[]{ + "custom configuration", + "custom config: system key = default (UNIX)", + "custom config: system key = UNIX", + "custom config: server time zone ID = " + getProject().getProperty("ftp.server.timezone"), + "custom config: system key = WINDOWS", + "custom config: default date format = yyyy/MM/dd HH:mm" + + }; + LogCounter counter = new LogCounter(); + for (int i=0; i < messages.length; i++) { + counter.addLogMessageToSearch(messages[i]); + } + + getProject().addBuildListener(counter); + getProject().executeTarget(target); + for (int i=0; i < messages.length; i++) { + assertEquals("target "+target+":message "+ i, expectedCounts[i], counter.getMatchCount(messages[i])); + } + + } + + /** * this test is inspired by a user reporting that deletions of directories with the ftp task do not work */