Didn't worry too much about WaitFor's backward compatibility issues as it is hardly a week old. WaitFor has ben modified this way so that it is consistent with Tstamp and takes in enumerated attributes for unit instead of allowing arbitrary letters/ words suffixed to the time. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@270074 13f79535-47bb-0310-9956-ffa450edef68master
@@ -9,67 +9,76 @@ | |||
<h2>Waitfor</h2> | |||
<h3>Description</h3> | |||
<p>Blocks execution until a set of specified conditions become true. This is intended | |||
to be used with the <a href="parallel.html">parallel</a> task to | |||
<p>Blocks execution until a set of specified conditions become true. This is intended | |||
to be used with the <a href="parallel.html">parallel</a> task to | |||
synchronize a set of processes.</p> | |||
<p>The conditions to wait for are defined in <a href="waitfor.html#nested">nested elements</a>, if multiple conditions | |||
are specified, then the task will wait until all conditions are true..</p> | |||
<p>The conditions to wait for are defined in <a href="waitfor.html#nested">nested elements</a>, | |||
if multiple conditions are specified, then the task will wait until all conditions are true..</p> | |||
<p></p> | |||
<p>The time attributes (maxwait and checkevery) are specified in milliseconds | |||
unless the values are followed by one of the following suffixes: "ms", | |||
"s", "m", "h" which cause the value to be interpreted | |||
as milliseconds, seconds, minutes or hours.</p> | |||
<p>If both maxwait and maxwaitunit are not specified, the maxwait is 3 minutes (180000 milliseconds).</p> | |||
<h3>Parameters</h3> | |||
<table border="1" cellpadding="2" cellspacing="0"> | |||
<tr> | |||
<tr> | |||
<td valign="top"><b>Attribute</b></td> | |||
<td valign="top"><b>Description</b></td> | |||
<td align="center" valign="top"><b>Required</b></td> | |||
</tr> | |||
<tr> | |||
<tr> | |||
<td valign="top">maxwait</td> | |||
<td valign="top">The maximum amount of time to wait for all the required conditions | |||
to become true before failing the task. Defaults to 5 minutes.</td> | |||
<td valign="top">The maximum amount of time to wait for all the required conditions | |||
to become true before failing the task. Defaults to 180000 maxwaitunits.</td> | |||
<td valign="top" align="center">No</td> | |||
</tr> | |||
<tr> | |||
<tr> | |||
<td valign="top">maxwaitunit</td> | |||
<td valign="top">The unit of time that must be used to interpret the value of the | |||
maxwait attribute. Defaults to millisecond.</td> | |||
<td valign="top" align="center">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">checkevery</td> | |||
<td valign="top">The amount of time to wait between each test of the conditions. | |||
Defaults to 200mS.</td> | |||
<td valign="top">The amount of time to wait between each test of the conditions. | |||
Defaults to 500 checkeveryunits.</td> | |||
<td valign="top" align="center">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">checkeveryunit</td> | |||
<td valign="top">The unit of time that must be used to interpret the value of the | |||
checkevery attribute. Defaults to millisecond.</td> | |||
<td valign="top" align="center">No</td> | |||
</tr> | |||
</table> | |||
<h3><a name="nested">Nested Elements</a></h3> | |||
<p>The available conditions that satisfy the | |||
<code><waitfor></code> task are the same as those for the | |||
<code><waitfor></code> task are the same as those for the | |||
<a href="condition.html"><code><condition></code></a> task. See | |||
<a href="conditions.html">here</a> for the full list.</p> | |||
<h3>Examples</h3> | |||
<blockquote> | |||
<p><code><waitfor maxwait="30s"><br> | |||
<blockquote> | |||
<p><code><waitfor maxwait="30" maxwaitunit="second"><br> | |||
<available file="errors.log"/><br> | |||
</waitfor></code></p> | |||
</blockquote> | |||
<p>waits up to 30 seconds for a file called errors.log to appear.</p> | |||
<blockquote> | |||
<p><code><waitfor maxwait="3m" checkevery="500ms"><br> | |||
<p><code><waitfor maxwait="3" maxwaitunit="minute" checkevery="500"><br> | |||
<http url="http://localhost/myapp/index.html"/><br> | |||
</waitfor></code></p> | |||
</blockquote> | |||
<p>waits up to 3 minutes (and checks every 500mS) for a web server on localhost | |||
<p>waits up to 3 minutes (and checks every 500 milliseconds) for a web server on localhost | |||
to serve up the specified URL.</p> | |||
<blockquote> | |||
<p><code><waitfor maxwait="10s"><br> | |||
<blockquote> | |||
<p><code><waitfor maxwait="10" maxwait="second"><br> | |||
<and><br> | |||
<socket server="dbserver" port="1521"/><br> | |||
<http url="http://webserver/mypage.html"/><br> | |||
</and><br> | |||
</waitfor></code></p> | |||
</blockquote> | |||
<p>waits up to 10 seconds for a server on the dbserver machine to begin listening | |||
on port 1521 and for the http://webserver/mypage.html web page | |||
<p>waits up to 10 seconds for a server on the dbserver machine to begin listening | |||
on port 1521 and for the http://webserver/mypage.html web page | |||
to become available.</p> | |||
<hr><p align="center">Copyright © 2000,2001 Apache Software Foundation. All rights | |||
Reserved.</p> | |||
@@ -75,13 +75,13 @@ import java.util.Hashtable; | |||
import java.util.Enumeration; | |||
/** | |||
* A consolidated copy task. Copies a file or directory to a new file | |||
* A consolidated copy task. Copies a file or directory to a new file | |||
* or directory. Files are only copied if the source file is newer | |||
* than the destination file, or when the destination file does not | |||
* than the destination file, or when the destination file does not | |||
* exist. It is possible to explicitly overwrite existing files.</p> | |||
* | |||
* <p>This implementation is based on Arnout Kuiper's initial design | |||
* document, the following mailing list discussions, and the | |||
* document, the following mailing list discussions, and the | |||
* copyfile/copydir tasks.</p> | |||
* | |||
* @author Glenn McAllister <a href="mailto:glennm@ca.ibm.com">glennm@ca.ibm.com</a> | |||
@@ -90,8 +90,8 @@ import java.util.Enumeration; | |||
* @author <a href="mailto:umagesh@rediffmail.com">Magesh Umasankar</a> | |||
*/ | |||
public class Copy extends Task { | |||
protected File file = null; // the source file | |||
protected File destFile = null; // the destination file | |||
protected File file = null; // the source file | |||
protected File destFile = null; // the destination file | |||
protected File destDir = null; // the destination directory | |||
protected Vector filesets = new Vector(); | |||
@@ -108,7 +108,7 @@ public class Copy extends Task { | |||
protected Mapper mapperElement = null; | |||
private Vector filterSets = new Vector(); | |||
private FileUtils fileUtils; | |||
public Copy() { | |||
fileUtils = FileUtils.newFileUtils(); | |||
} | |||
@@ -144,12 +144,22 @@ public class Copy extends Task { | |||
filterSets.addElement(filterSet); | |||
return filterSet; | |||
} | |||
/** | |||
* Give the copied files the same last modified time as the original files. | |||
* @deprecated setPreserveLastModified(String) has been deprecated and | |||
* replaced with setPreserveLastModified(boolean) to | |||
* consistently let the Introspection mechanism work. | |||
*/ | |||
public void setPreserveLastModified(String preserve) { | |||
preserveLastModified = Project.toBoolean(preserve); | |||
setPreserveLastModified(Project.toBoolean(preserve)); | |||
} | |||
/** | |||
* Give the copied files the same last modified time as the original files. | |||
*/ | |||
public void setPreserveLastModified(boolean preserve) { | |||
preserveLastModified = preserve; | |||
} | |||
/** | |||
@@ -160,7 +170,7 @@ public class Copy extends Task { | |||
protected Vector getFilterSets() { | |||
return filterSets; | |||
} | |||
/** | |||
* Sets filtering. | |||
*/ | |||
@@ -194,8 +204,8 @@ public class Copy extends Task { | |||
this.verbosity = Project.MSG_INFO; | |||
} else { | |||
this.verbosity = Project.MSG_VERBOSE; | |||
} | |||
} | |||
} | |||
} | |||
/** | |||
* Used to copy empty directories. | |||
@@ -228,7 +238,7 @@ public class Copy extends Task { | |||
*/ | |||
public void execute() throws BuildException { | |||
// make sure we don't have an illegal set of options | |||
validateAttributes(); | |||
validateAttributes(); | |||
// deal with the single file | |||
if (file != null) { | |||
@@ -236,8 +246,8 @@ public class Copy extends Task { | |||
if (destFile == null) { | |||
destFile = new File(destDir, file.getName()); | |||
} | |||
if (forceOverwrite || | |||
if (forceOverwrite || | |||
(file.lastModified() > destFile.lastModified())) { | |||
fileCopyMap.put(file.getAbsolutePath(), destFile.getAbsolutePath()); | |||
} else { | |||
@@ -245,7 +255,7 @@ public class Copy extends Task { | |||
Project.MSG_VERBOSE); | |||
} | |||
} else { | |||
String message = "Could not find file " | |||
String message = "Could not find file " | |||
+ file.getAbsolutePath() + " to copy."; | |||
log(message); | |||
throw new BuildException(message); | |||
@@ -280,7 +290,7 @@ public class Copy extends Task { | |||
/** | |||
* Ensure we have a consistent and legal set of attributes, and set | |||
* any internal flags necessary based on different combinations | |||
* any internal flags necessary based on different combinations | |||
* of attributes. | |||
*/ | |||
protected void validateAttributes() throws BuildException { | |||
@@ -299,7 +309,7 @@ public class Copy extends Task { | |||
if (file != null && file.exists() && file.isDirectory()) { | |||
throw new BuildException("Use a fileset to copy directories."); | |||
} | |||
if (destFile != null && filesets.size() > 0) { | |||
if (filesets.size() > 1) { | |||
throw new BuildException( | |||
@@ -368,7 +378,7 @@ public class Copy extends Task { | |||
SourceFileScanner ds = new SourceFileScanner(this); | |||
toCopy = ds.restrict(names, fromDir, toDir, mapper); | |||
} | |||
for (int i = 0; i < toCopy.length; i++) { | |||
File src = new File(fromDir, toCopy[i]); | |||
File dest = new File(toDir, mapper.mapFileName(toCopy[i])[0]); | |||
@@ -382,8 +392,8 @@ public class Copy extends Task { | |||
*/ | |||
protected void doFileOperations() { | |||
if (fileCopyMap.size() > 0) { | |||
log("Copying " + fileCopyMap.size() + | |||
" file" + (fileCopyMap.size() == 1 ? "" : "s") + | |||
log("Copying " + fileCopyMap.size() + | |||
" file" + (fileCopyMap.size() == 1 ? "" : "s") + | |||
" to " + destDir.getAbsolutePath() ); | |||
Enumeration e = fileCopyMap.keys(); | |||
@@ -398,7 +408,7 @@ public class Copy extends Task { | |||
try { | |||
log("Copying " + fromFile + " to " + toFile, verbosity); | |||
FilterSetCollection executionFilters = new FilterSetCollection(); | |||
if (filtering) { | |||
executionFilters.addFilterSet(project.getGlobalFilterSet()); | |||
@@ -431,9 +441,9 @@ public class Copy extends Task { | |||
} | |||
if (count > 0) { | |||
log("Copied " + count + | |||
" empty director" + | |||
(count==1?"y":"ies") + | |||
log("Copied " + count + | |||
" empty director" + | |||
(count==1?"y":"ies") + | |||
" to " + destDir.getAbsolutePath()); | |||
} | |||
} | |||
@@ -55,14 +55,11 @@ | |||
package org.apache.tools.ant.taskdefs; | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.Project; | |||
import org.apache.tools.ant.taskdefs.condition.ConditionBase; | |||
import org.apache.tools.ant.taskdefs.condition.Condition; | |||
import org.apache.tools.ant.types.EnumeratedAttribute; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.net.*; | |||
import java.util.Vector; | |||
import java.util.Hashtable; | |||
/** | |||
* Wait for an external event to occur. | |||
@@ -74,32 +71,48 @@ import java.util.Vector; | |||
* The following attributes can be specified on a waitfor task: | |||
* <ul> | |||
* <li>maxwait - maximum length of time to wait before giving up</li> | |||
* <li>maxwaitunit - The unit to be used to interpret maxwait attribute</li> | |||
* <li>checkevery - amount of time to sleep between each check</li> | |||
* <li>checkeveryunit - The unit to be used to interpret checkevery attribute</li> | |||
* </ul> | |||
* | |||
* The time value can include a suffix of "ms", "s", "m", "h" to | |||
* indicate that the value is in milliseconds, seconds, minutes or | |||
* hours. The default is milliseconds. | |||
* The maxwaitunit and checkeveryunit are allowed to have the following values: | |||
* millesond, second, minute, hour, day and week. The default is millisecond. | |||
* | |||
* @author <a href="mailto:denis@network365.com">Denis Hennessy</a> | |||
* @author <a href="mailto:umagesh@apache.org">Magesh Umasankar</a> | |||
*/ | |||
public class WaitFor extends ConditionBase { | |||
private long maxWaitMillis = 1000 * 60 * 3; // default max wait time | |||
private long checkEveryMillis = 500; | |||
private long maxWaitMillis = 1000l * 60l * 3l; // default max wait time | |||
private long checkEveryMillis = 500l; | |||
/** | |||
* Set the maximum length of time to wait | |||
*/ | |||
public void setMaxWait(String time) { | |||
maxWaitMillis = parseTime(time); | |||
public void setMaxWait(long time) { | |||
maxWaitMillis = time; | |||
} | |||
/** | |||
* Set the max wait time unit | |||
*/ | |||
public void setMaxWaitUnit(Unit unit) { | |||
maxWaitMillis *= unit.getMultiplier(); | |||
} | |||
/** | |||
* Set the time between each check | |||
*/ | |||
public void setCheckEvery(String time) { | |||
checkEveryMillis = parseTime(time); | |||
public void setCheckEvery(long time) { | |||
checkEveryMillis = time; | |||
} | |||
/** | |||
* Set the check every time unit | |||
*/ | |||
public void setCheckEveryUnit(Unit unit) { | |||
checkEveryMillis *= unit.getMultiplier(); | |||
} | |||
/** | |||
@@ -131,44 +144,38 @@ public class WaitFor extends ConditionBase { | |||
throw new BuildException("Task did not complete in time"); | |||
} | |||
/** | |||
* Parse a time in the format nnnnnxx where xx is a common time | |||
* multiplier suffix. | |||
*/ | |||
protected long parseTime(String value) { | |||
int i = 0; | |||
for (i = 0; i < value.length(); i++) { | |||
char ch = value.charAt(i); | |||
if (ch < '0' || ch > '9') { | |||
break; | |||
} | |||
} | |||
if (i == 0) { | |||
throw new NumberFormatException(); | |||
} | |||
String digits = value.substring(0, i); | |||
return Long.parseLong(digits) * getMultiplier(value.substring(i)); | |||
} | |||
public static class Unit extends EnumeratedAttribute { | |||
/** | |||
* Look for and decipher a multiplier suffix in the string. | |||
* @param value - a string with a series of digits followed by the | |||
* scale suffix. | |||
*/ | |||
protected long getMultiplier(String value) { | |||
String lowercaseValue = value.toLowerCase(); | |||
if (lowercaseValue.startsWith("ms")) { | |||
return 1; | |||
} | |||
if (lowercaseValue.startsWith("s")) { | |||
return 1000; | |||
private static final String MILLISECOND = "millisecond"; | |||
private static final String SECOND = "second"; | |||
private static final String MINUTE = "minute"; | |||
private static final String HOUR = "hour"; | |||
private static final String DAY = "day"; | |||
private static final String WEEK = "week"; | |||
private final static String[] units = { | |||
MILLISECOND, SECOND, MINUTE, HOUR, DAY, WEEK | |||
}; | |||
private Hashtable timeTable = new Hashtable(); | |||
public Unit() { | |||
timeTable.put(MILLISECOND, new Long(1l)); | |||
timeTable.put(SECOND, new Long(1000l)); | |||
timeTable.put(MINUTE, new Long(1000l * 60l)); | |||
timeTable.put(HOUR, new Long(1000l * 60l * 60l)); | |||
timeTable.put(DAY, new Long(1000l * 60l * 60l * 24l)); | |||
timeTable.put(WEEK, new Long(1000l * 60l * 60l * 24l * 7l)); | |||
} | |||
if (lowercaseValue.startsWith("m")) { | |||
return 1000 * 60; | |||
public long getMultiplier() { | |||
String key = getValue().toLowerCase(); | |||
Long l = (Long) timeTable.get(key); | |||
return l.longValue(); | |||
} | |||
if (lowercaseValue.startsWith("h")) { | |||
return 1000 * 60 * 60; | |||
public String[] getValues() { | |||
return units; | |||
} | |||
return 1; | |||
} | |||
} |