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 | |||
*/ | |||