and add some JUnit tests of the new configuration stuff. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@278372 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -14,6 +14,7 @@ | |||
| <property name="tstamp.format" value="yyyy-MM-dd HH:mm"/> | |||
| <property name="server.timestamp.granularity.millis" value="60000"/> | |||
| <property name="ftp.server.timezone" value="GMT"/> | |||
| <property name="ftp.listing.file" value="/dev/null"/> | |||
| <fileset dir="${tmp.get.dir}" id="fileset-destination-with-selector"> | |||
| <include name="alpha/**"/> | |||
| @@ -191,5 +192,59 @@ | |||
| </fileset> | |||
| </ftp> | |||
| </target> | |||
| <target name="configuration.1"> | |||
| <ftp action="list" | |||
| server="${ftp.host}" | |||
| userid="${ftp.user}" | |||
| password="${ftp.password}" | |||
| separator="${ftp.filesep}" | |||
| remotedir="${tmp.remote}" | |||
| serverTimeZoneConfig="${ftp.server.timezone}" | |||
| listing="${ftp.listing.file}" | |||
| > | |||
| <fileset dir="${tmp.local}"/> | |||
| </ftp> | |||
| </target> | |||
| <target name="configuration.2"> | |||
| <ftp action="list" | |||
| server="${ftp.host}" | |||
| userid="${ftp.user}" | |||
| password="${ftp.password}" | |||
| separator="${ftp.filesep}" | |||
| remotedir="${tmp.remote}" | |||
| serverTimeZoneConfig="${ftp.server.timezone}" | |||
| listing="${ftp.listing.file}" | |||
| systemTypeKey="WINDOWS" | |||
| > | |||
| <fileset dir="${tmp.local}"/> | |||
| </ftp> | |||
| </target> | |||
| <target name="configuration.3"> | |||
| <ftp action="list" | |||
| server="${ftp.host}" | |||
| userid="${ftp.user}" | |||
| password="${ftp.password}" | |||
| separator="${ftp.filesep}" | |||
| remotedir="${tmp.remote}" | |||
| defaultDateFormatConfig="yyyy/MM/dd HH:mm" | |||
| listing="${ftp.listing.file}" | |||
| systemTypeKey="UNIX" | |||
| > | |||
| <fileset dir="${tmp.local}"/> | |||
| </ftp> | |||
| </target> | |||
| <target name="configuration.none"> | |||
| <ftp action="list" | |||
| server="${ftp.host}" | |||
| userid="${ftp.user}" | |||
| password="${ftp.password}" | |||
| separator="${ftp.filesep}" | |||
| remotedir="${tmp.remote}" | |||
| listing="${ftp.listing.file}" | |||
| > | |||
| <fileset dir="${tmp.local}"/> | |||
| </ftp> | |||
| </target> | |||
| </project> | |||
| @@ -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 <code>timestampGranularity</code> attribute.<p> | |||
| * 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 <code>preserveLastModified</code> | |||
| * 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; | |||
| } | |||
| } | |||
| } | |||
| @@ -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(); | |||
| @@ -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 | |||
| */ | |||