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="tstamp.format" value="yyyy-MM-dd HH:mm"/> | ||||
<property name="server.timestamp.granularity.millis" value="60000"/> | <property name="server.timestamp.granularity.millis" value="60000"/> | ||||
<property name="ftp.server.timezone" value="GMT"/> | <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"> | <fileset dir="${tmp.get.dir}" id="fileset-destination-with-selector"> | ||||
<include name="alpha/**"/> | <include name="alpha/**"/> | ||||
@@ -191,5 +192,59 @@ | |||||
</fileset> | </fileset> | ||||
</ftp> | </ftp> | ||||
</target> | </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> | </project> |
@@ -101,6 +101,7 @@ public class FTP | |||||
private boolean verbose = false; | private boolean verbose = false; | ||||
private boolean newerOnly = false; | private boolean newerOnly = false; | ||||
private long timeDiffMillis = 0; | private long timeDiffMillis = 0; | ||||
private long granularityMillis = 0L; | |||||
private boolean timeDiffAuto = false; | private boolean timeDiffAuto = false; | ||||
private int action = SEND_FILES; | private int action = SEND_FILES; | ||||
private Vector filesets = new Vector(); | private Vector filesets = new Vector(); | ||||
@@ -114,14 +115,13 @@ public class FTP | |||||
private boolean preserveLastModified = false; | private boolean preserveLastModified = false; | ||||
private String chmod = null; | private String chmod = null; | ||||
private String umask = null; | private String umask = null; | ||||
private String systemTypeKey = null; | |||||
private FTPSystemType systemTypeKey = FTPSystemType.getDefault(); | |||||
private String defaultDateFormatConfig = null; | private String defaultDateFormatConfig = null; | ||||
private String recentDateFormatConfig = null; | private String recentDateFormatConfig = null; | ||||
private String serverLanguageCodeConfig = null; | private String serverLanguageCodeConfig = null; | ||||
private String serverTimeZoneConfig = null; | private String serverTimeZoneConfig = null; | ||||
private String shortMonthNamesConfig = null; | private String shortMonthNamesConfig = null; | ||||
private String timestampGranularity = null; | |||||
private long serverTimestampGranularity = 0L; | |||||
private Granularity timestampGranularity = Granularity.getDefault(); | |||||
private boolean isConfigurationSet = false; | private boolean isConfigurationSet = false; | ||||
protected static final String[] ACTION_STRS = { | protected static final String[] ACTION_STRS = { | ||||
@@ -1268,8 +1268,8 @@ public class FTP | |||||
* the default value of null will be kept. | * the default value of null will be kept. | ||||
* @see org.apache.commons.net.ftp.FTPClientConfig | * @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; | this.systemTypeKey = systemKey; | ||||
configurationHasBeenSet(); | configurationHasBeenSet(); | ||||
@@ -1361,7 +1361,7 @@ public class FTP | |||||
* @return Returns the systemTypeKey. | * @return Returns the systemTypeKey. | ||||
*/ | */ | ||||
String getSystemTypeKey() { | String getSystemTypeKey() { | ||||
return systemTypeKey; | |||||
return systemTypeKey.getValue(); | |||||
} | } | ||||
/** | /** | ||||
* @return Returns the defaultDateFormatConfig. | * @return Returns the defaultDateFormatConfig. | ||||
@@ -1396,13 +1396,13 @@ public class FTP | |||||
/** | /** | ||||
* @return Returns the timestampGranularity. | * @return Returns the timestampGranularity. | ||||
*/ | */ | ||||
String getTimestampGranularity() { | |||||
Granularity getTimestampGranularity() { | |||||
return timestampGranularity; | return timestampGranularity; | ||||
} | } | ||||
/** | /** | ||||
* @param timestampGranularity The timestampGranularity to set. | * @param timestampGranularity The timestampGranularity to set. | ||||
*/ | */ | ||||
public void setTimestampGranularity(String timestampGranularity) { | |||||
public void setTimestampGranularity(Granularity timestampGranularity) { | |||||
if (null == timestampGranularity || "".equals(timestampGranularity)) { | if (null == timestampGranularity || "".equals(timestampGranularity)) { | ||||
return; | return; | ||||
} | } | ||||
@@ -1517,29 +1517,8 @@ public class FTP | |||||
} | } | ||||
} else { | } else { | ||||
if (this.newerOnly) { | 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++) { | for (int i = 0; i < dsfiles.length; i++) { | ||||
switch (action) { | switch (action) { | ||||
@@ -1799,13 +1778,13 @@ public class FTP | |||||
if (this.action == SEND_FILES) { | if (this.action == SEND_FILES) { | ||||
return remoteTimestamp | return remoteTimestamp | ||||
+ this.timeDiffMillis | + this.timeDiffMillis | ||||
+ this.serverTimestampGranularity | |||||
+ this.granularityMillis | |||||
>= localTimestamp; | >= localTimestamp; | ||||
} else { | } else { | ||||
return localTimestamp | return localTimestamp | ||||
>= remoteTimestamp | >= remoteTimestamp | ||||
+ this.timeDiffMillis | + this.timeDiffMillis | ||||
+ this.serverTimestampGranularity; | |||||
+ this.granularityMillis; | |||||
} | } | ||||
} | } | ||||
@@ -2300,5 +2279,84 @@ public class FTP | |||||
return SEND_FILES; | 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. | * @return the client as configured. | ||||
*/ | */ | ||||
static FTPClient configure(FTPClient client, FTP task) { | static FTPClient configure(FTPClient client, FTP task) { | ||||
task.log("custom configuration", Project.MSG_VERBOSE); | |||||
FTPClientConfig config; | FTPClientConfig config; | ||||
String systemTypeKey = task.getSystemTypeKey(); | String systemTypeKey = task.getSystemTypeKey(); | ||||
if (systemTypeKey != null) { | |||||
if (systemTypeKey != null && !"".equals(systemTypeKey)) { | |||||
config = new FTPClientConfig(systemTypeKey); | config = new FTPClientConfig(systemTypeKey); | ||||
task.log("custom config: system key = " | task.log("custom config: system key = " | ||||
+ systemTypeKey, Project.MSG_VERBOSE); | + systemTypeKey, Project.MSG_VERBOSE); | ||||
} else { | } else { | ||||
config = new FTPClientConfig(); | config = new FTPClientConfig(); | ||||
task.log("custom config: system key = default (UNIX)", | |||||
Project.MSG_VERBOSE); | |||||
} | } | ||||
String defaultDateFormatConfig = task.getDefaultDateFormatConfig(); | String defaultDateFormatConfig = task.getDefaultDateFormatConfig(); | ||||
@@ -16,25 +16,23 @@ | |||||
*/ | */ | ||||
package org.apache.tools.ant.taskdefs.optional.net; | 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.BuildEvent; | ||||
import org.apache.tools.ant.BuildFileTest; | 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.DefaultLogger; | ||||
import org.apache.tools.ant.DirectoryScanner; | 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.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.RegexpMatcher; | ||||
import org.apache.tools.ant.util.regexp.RegexpMatcherFactory; | 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{ | public class FTPTest extends BuildFileTest{ | ||||
// keep track of what operating systems are supported here. | // 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 | * Tests the combination of the newer parameter and the | ||||
* serverTimezoneConfig parameter in the PUT action. The default | * serverTimezoneConfig parameter in the PUT action. The default | ||||
@@ -619,7 +653,76 @@ public class FTPTest extends BuildFileTest{ | |||||
getProject().executeTarget("timed.test.get.older"); | getProject().executeTarget("timed.test.get.older"); | ||||
assertEquals(3, log.getCount()); | 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 | * this test is inspired by a user reporting that deletions of directories with the ftp task do not work | ||||
*/ | */ | ||||