git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@805265 13f79535-47bb-0310-9956-ffa450edef68master
@@ -836,6 +836,9 @@ Other changes: | |||||
arbitrary JDBC connection properties. | arbitrary JDBC connection properties. | ||||
Bugzilla Report 33452. | Bugzilla Report 33452. | ||||
* A new islastmodified condition can check the last modified date of | |||||
resources. | |||||
Changes from Ant 1.7.0 TO Ant 1.7.1 | Changes from Ant 1.7.0 TO Ant 1.7.1 | ||||
============================================= | ============================================= | ||||
@@ -1007,5 +1007,55 @@ is redundant and will be ignored.</p> | |||||
<blockquote><pre> | <blockquote><pre> | ||||
<hasfreespace partition="c:" needed="100M"/> | <hasfreespace partition="c:" needed="100M"/> | ||||
</pre></blockquote> | </pre></blockquote> | ||||
<h4>islastmodified</h4> | |||||
<p>Tests the last modified date of a resource. <em>Since Ant | |||||
1.8.0</em></p> | |||||
<table border="1" cellpadding="2" cellspacing="0"> | |||||
<tr> | |||||
<td width="12%" valign="top"><b>Attribute</b></td> | |||||
<td width="78%" valign="top"><b>Description</b></td> | |||||
<td width="10%" valign="top"><b>Required</b></td> | |||||
</tr> | |||||
<tr> | |||||
<td valign="top">millis</td> | |||||
<td valign="top">Specifies the expected modification time of the resource | |||||
in milliseconds since midnight Jan 1 1970.</td> | |||||
<td valign="center" align="center" rowspan="2">Exactly one of the | |||||
two.</td> | |||||
</tr> | |||||
<tr> | |||||
<td valign="top">datetime</td> | |||||
<td valign="top">Specifies the expected modification time of the | |||||
resource. The special value "now" indicates the | |||||
current time.</td> | |||||
</tr> | |||||
<tr> | |||||
<td valign="top">pattern</td> | |||||
<td valign="top">SimpleDateFormat-compatible pattern string. | |||||
Defaults to MM/DD/YYYY HH:MM AM_or_PM or MM/DD/YYYY HH:MM:SS AM_or_PM. | |||||
</td> | |||||
<td valign="top" align="center">No</td> | |||||
</tr> | |||||
<tr> | |||||
<td valign="top">mode</td> | |||||
<td valign="top">How to compare the timestamp. Accepted values | |||||
are "equals", "before", "not-before", "after" and "not-after". | |||||
<td valign="top">No, defaults to "equals".</td> | |||||
</tr> | |||||
</table> | |||||
<p>The actual resource to test is specified as a nested element.</p> | |||||
<p> | |||||
An example: | |||||
</p> | |||||
<blockquote><pre> | |||||
<islastmodified dateTime="08/18/2009 04:41:19 AM" mode="not-before"> | |||||
<file file="${file}"/> | |||||
</islastmodified> | |||||
</pre></blockquote> | |||||
</body> | </body> | ||||
</html> | </html> |
@@ -54,12 +54,12 @@ import org.apache.tools.ant.util.FileNameMapper; | |||||
*/ | */ | ||||
public class Touch extends Task { | public class Touch extends Task { | ||||
private interface DateFormatFactory { | |||||
public interface DateFormatFactory { | |||||
DateFormat getPrimaryFormat(); | DateFormat getPrimaryFormat(); | ||||
DateFormat getFallbackFormat(); | DateFormat getFallbackFormat(); | ||||
} | } | ||||
private static final DateFormatFactory DEFAULT_DF_FACTORY | |||||
public static final DateFormatFactory DEFAULT_DF_FACTORY | |||||
= new DateFormatFactory() { | = new DateFormatFactory() { | ||||
/* | /* | ||||
* The initial version used DateFormat.SHORT for the | * The initial version used DateFormat.SHORT for the | ||||
@@ -0,0 +1,193 @@ | |||||
/* | |||||
* Licensed to the Apache Software Foundation (ASF) under one or more | |||||
* contributor license agreements. See the NOTICE file distributed with | |||||
* this work for additional information regarding copyright ownership. | |||||
* The ASF licenses this file to You under the Apache License, Version 2.0 | |||||
* (the "License"); you may not use this file except in compliance with | |||||
* the License. You may obtain a copy of the License at | |||||
* | |||||
* http://www.apache.org/licenses/LICENSE-2.0 | |||||
* | |||||
* Unless required by applicable law or agreed to in writing, software | |||||
* distributed under the License is distributed on an "AS IS" BASIS, | |||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
* See the License for the specific language governing permissions and | |||||
* limitations under the License. | |||||
* | |||||
*/ | |||||
package org.apache.tools.ant.taskdefs.condition; | |||||
import java.text.DateFormat; | |||||
import java.text.ParseException; | |||||
import java.text.SimpleDateFormat; | |||||
import org.apache.tools.ant.BuildException; | |||||
import org.apache.tools.ant.ProjectComponent; | |||||
import org.apache.tools.ant.taskdefs.Touch; | |||||
import org.apache.tools.ant.types.EnumeratedAttribute; | |||||
import org.apache.tools.ant.types.Resource; | |||||
/** | |||||
* Condition that makes assertions about the last modified date of a | |||||
* resource. | |||||
* | |||||
* @since Ant 1.8.0 | |||||
*/ | |||||
public class IsLastModified extends ProjectComponent implements Condition { | |||||
private long millis = -1; | |||||
private String dateTime = null; | |||||
private Touch.DateFormatFactory dfFactory = Touch.DEFAULT_DF_FACTORY; | |||||
private Resource resource; | |||||
private CompareMode mode = CompareMode.EQUALS; | |||||
/** | |||||
* Set the new modification time of file(s) touched | |||||
* in milliseconds since midnight Jan 1 1970. | |||||
* @param millis the <code>long</code> timestamp to use. | |||||
*/ | |||||
public void setMillis(long millis) { | |||||
this.millis = millis; | |||||
} | |||||
/** | |||||
* Set the new modification time of file(s) touched | |||||
* in the format "MM/DD/YYYY HH:MM AM <i>or</i> PM" | |||||
* or "MM/DD/YYYY HH:MM:SS AM <i>or</i> PM". | |||||
* @param dateTime the <code>String</code> date in the specified format. | |||||
*/ | |||||
public void setDatetime(String dateTime) { | |||||
this.dateTime = dateTime; | |||||
} | |||||
/** | |||||
* Set the format of the datetime attribute. | |||||
* @param pattern the <code>SimpleDateFormat</code>-compatible | |||||
* format pattern. | |||||
*/ | |||||
public void setPattern(final String pattern) { | |||||
dfFactory = new Touch.DateFormatFactory() { | |||||
public DateFormat getPrimaryFormat() { | |||||
return new SimpleDateFormat(pattern); | |||||
} | |||||
public DateFormat getFallbackFormat() { | |||||
return null; | |||||
} | |||||
}; | |||||
} | |||||
/** | |||||
* The resource to test. | |||||
*/ | |||||
public void add(Resource r) { | |||||
if (resource != null) { | |||||
throw new BuildException("only one resource can be tested"); | |||||
} | |||||
resource = r; | |||||
} | |||||
/** | |||||
* The type of comparison to test. | |||||
*/ | |||||
public void setMode(CompareMode mode) { | |||||
this.mode = mode; | |||||
} | |||||
/** | |||||
* Argument validation. | |||||
*/ | |||||
protected void validate() throws BuildException { | |||||
if (millis >= 0 && dateTime != null) { | |||||
throw new BuildException("Only one of dateTime and millis can be" | |||||
+ " set"); | |||||
} | |||||
if (millis < 0 && dateTime == null) { | |||||
throw new BuildException("millis or dateTime is required"); | |||||
} | |||||
if (resource == null) { | |||||
throw new BuildException("resource is required"); | |||||
} | |||||
} | |||||
/** | |||||
* Calculate timestamp as millis either based on millis or | |||||
* dateTime (and pattern) attribute. | |||||
*/ | |||||
protected long getMillis() throws BuildException { | |||||
if (millis >= 0) { | |||||
return millis; | |||||
} | |||||
if ("now".equalsIgnoreCase(dateTime)) { | |||||
return System.currentTimeMillis(); | |||||
} | |||||
DateFormat df = dfFactory.getPrimaryFormat(); | |||||
ParseException pe = null; | |||||
try { | |||||
return df.parse(dateTime).getTime(); | |||||
} catch (ParseException peOne) { | |||||
df = dfFactory.getFallbackFormat(); | |||||
if (df == null) { | |||||
pe = peOne; | |||||
} else { | |||||
try { | |||||
return df.parse(dateTime).getTime(); | |||||
} catch (ParseException peTwo) { | |||||
pe = peTwo; | |||||
} | |||||
} | |||||
} | |||||
if (pe != null) { | |||||
throw new BuildException(pe.getMessage(), pe, getLocation()); | |||||
} | |||||
/* NOTREACHED */ | |||||
return 0; | |||||
} | |||||
public boolean eval() throws BuildException { | |||||
validate(); | |||||
long expected = getMillis(); | |||||
long actual = resource.getLastModified(); | |||||
if (CompareMode.EQUALS_TEXT.equals(mode.getValue())) { | |||||
return expected == actual; | |||||
} | |||||
if (CompareMode.BEFORE_TEXT.equals(mode.getValue())) { | |||||
return expected > actual; | |||||
} | |||||
if (CompareMode.NOT_BEFORE_TEXT.equals(mode.getValue())) { | |||||
return expected <= actual; | |||||
} | |||||
if (CompareMode.AFTER_TEXT.equals(mode.getValue())) { | |||||
return expected < actual; | |||||
} | |||||
if (CompareMode.NOT_AFTER_TEXT.equals(mode.getValue())) { | |||||
return expected >= actual; | |||||
} | |||||
throw new BuildException("Unknown mode " + mode.getValue()); | |||||
} | |||||
public static class CompareMode extends EnumeratedAttribute { | |||||
private static final String EQUALS_TEXT = "equals"; | |||||
private static final String BEFORE_TEXT = "before"; | |||||
private static final String AFTER_TEXT = "after"; | |||||
private static final String NOT_BEFORE_TEXT = "not-before"; | |||||
private static final String NOT_AFTER_TEXT = "not-after"; | |||||
private static final CompareMode EQUALS = new CompareMode(EQUALS_TEXT); | |||||
public CompareMode() { | |||||
this(EQUALS_TEXT); | |||||
} | |||||
public CompareMode(String s) { | |||||
super(); | |||||
setValue(s); | |||||
} | |||||
public String[] getValues() { | |||||
return new String[] { | |||||
EQUALS_TEXT, BEFORE_TEXT, AFTER_TEXT, NOT_BEFORE_TEXT, | |||||
NOT_AFTER_TEXT, | |||||
}; | |||||
} | |||||
} | |||||
} |
@@ -21,7 +21,7 @@ | |||||
--> | --> | ||||
<!-- Ant 1.6+ antlib declaration for conditions: | <!-- Ant 1.6+ antlib declaration for conditions: | ||||
Use with the declaration xmlns:cond="antlib:org.apache.tools.ant.condition" | |||||
Use with the declaration xmlns:cond="antlib:org.apache.tools.ant.types.conditions" | |||||
to | to | ||||
trigger Ant's autoload of this file into namespace 'cond' (or whatever name | trigger Ant's autoload of this file into namespace 'cond' (or whatever name | ||||
suits). | suits). | ||||
@@ -54,6 +54,8 @@ | |||||
classname="org.apache.tools.ant.taskdefs.condition.IsFalse"/> | classname="org.apache.tools.ant.taskdefs.condition.IsFalse"/> | ||||
<typedef name="isfileselected" onerror="ignore" | <typedef name="isfileselected" onerror="ignore" | ||||
classname="org.apache.tools.ant.taskdefs.condition.IsFileSelected"/> | classname="org.apache.tools.ant.taskdefs.condition.IsFileSelected"/> | ||||
<typedef name="islastmodified" onerror="ignore" | |||||
classname="org.apache.tools.ant.taskdefs.condition.IsLastModified"/> | |||||
<typedef name="isreachable" onerror="ignore" | <typedef name="isreachable" onerror="ignore" | ||||
classname="org.apache.tools.ant.taskdefs.condition.IsReachable"/> | classname="org.apache.tools.ant.taskdefs.condition.IsReachable"/> | ||||
<typedef name="isreference" onerror="ignore" | <typedef name="isreference" onerror="ignore" | ||||
@@ -86,4 +88,4 @@ | |||||
classname="org.apache.tools.ant.taskdefs.condition.TypeFound"/> | classname="org.apache.tools.ant.taskdefs.condition.TypeFound"/> | ||||
<typedef name="xor" onerror="ignore" | <typedef name="xor" onerror="ignore" | ||||
classname="org.apache.tools.ant.taskdefs.condition.Xor"/> | classname="org.apache.tools.ant.taskdefs.condition.Xor"/> | ||||
</antlib> | |||||
</antlib> |
@@ -0,0 +1,118 @@ | |||||
<?xml version="1.0"?> | |||||
<!-- | |||||
Licensed to the Apache Software Foundation (ASF) under one or more | |||||
contributor license agreements. See the NOTICE file distributed with | |||||
this work for additional information regarding copyright ownership. | |||||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||||
(the "License"); you may not use this file except in compliance with | |||||
the License. You may obtain a copy of the License at | |||||
http://www.apache.org/licenses/LICENSE-2.0 | |||||
Unless required by applicable law or agreed to in writing, software | |||||
distributed under the License is distributed on an "AS IS" BASIS, | |||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
See the License for the specific language governing permissions and | |||||
limitations under the License. | |||||
--> | |||||
<project xmlns:au="antlib:org.apache.ant.antunit" default="antunit" | |||||
xmlns:cond="antlib:org.apache.tools.ant.types.conditions"> | |||||
<import file="../../antunit-base.xml"/> | |||||
<target name="setUp"> | |||||
<mkdir dir="${output}"/> | |||||
<property name="file" location="${output}/test.txt"/> | |||||
<touch file="${file}" dateTime="08/18/2009 04:41:20 AM"/> | |||||
</target> | |||||
<target name="testEquals" depends="setUp"> | |||||
<au:assertFalse> | |||||
<cond:islastmodified dateTime="08/18/2009 04:41:19 AM"> | |||||
<file file="${file}"/> | |||||
</cond:islastmodified> | |||||
</au:assertFalse> | |||||
<au:assertTrue> | |||||
<cond:islastmodified dateTime="08/18/2009 04:41:20 AM"> | |||||
<file file="${file}"/> | |||||
</cond:islastmodified> | |||||
</au:assertTrue> | |||||
<au:assertFalse> | |||||
<cond:islastmodified dateTime="08/18/2009 04:41:21 AM"> | |||||
<file file="${file}"/> | |||||
</cond:islastmodified> | |||||
</au:assertFalse> | |||||
</target> | |||||
<target name="testBefore" depends="setUp"> | |||||
<au:assertFalse> | |||||
<cond:islastmodified dateTime="08/18/2009 04:41:19 AM" mode="before"> | |||||
<file file="${file}"/> | |||||
</cond:islastmodified> | |||||
</au:assertFalse> | |||||
<au:assertFalse> | |||||
<cond:islastmodified dateTime="08/18/2009 04:41:20 AM" mode="before"> | |||||
<file file="${file}"/> | |||||
</cond:islastmodified> | |||||
</au:assertFalse> | |||||
<au:assertTrue> | |||||
<cond:islastmodified dateTime="08/18/2009 04:41:21 AM" mode="before"> | |||||
<file file="${file}"/> | |||||
</cond:islastmodified> | |||||
</au:assertTrue> | |||||
</target> | |||||
<target name="testAfter" depends="setUp"> | |||||
<au:assertTrue> | |||||
<cond:islastmodified dateTime="08/18/2009 04:41:19 AM" mode="after"> | |||||
<file file="${file}"/> | |||||
</cond:islastmodified> | |||||
</au:assertTrue> | |||||
<au:assertFalse> | |||||
<cond:islastmodified dateTime="08/18/2009 04:41:20 AM" mode="after"> | |||||
<file file="${file}"/> | |||||
</cond:islastmodified> | |||||
</au:assertFalse> | |||||
<au:assertFalse> | |||||
<cond:islastmodified dateTime="08/18/2009 04:41:21 AM" mode="after"> | |||||
<file file="${file}"/> | |||||
</cond:islastmodified> | |||||
</au:assertFalse> | |||||
</target> | |||||
<target name="testNotBefore" depends="setUp"> | |||||
<au:assertTrue> | |||||
<cond:islastmodified dateTime="08/18/2009 04:41:19 AM" mode="not-before"> | |||||
<file file="${file}"/> | |||||
</cond:islastmodified> | |||||
</au:assertTrue> | |||||
<au:assertTrue> | |||||
<cond:islastmodified dateTime="08/18/2009 04:41:20 AM" mode="not-before"> | |||||
<file file="${file}"/> | |||||
</cond:islastmodified> | |||||
</au:assertTrue> | |||||
<au:assertFalse> | |||||
<cond:islastmodified dateTime="08/18/2009 04:41:21 AM" mode="not-before"> | |||||
<file file="${file}"/> | |||||
</cond:islastmodified> | |||||
</au:assertFalse> | |||||
</target> | |||||
<target name="testNotAfter" depends="setUp"> | |||||
<au:assertFalse> | |||||
<cond:islastmodified dateTime="08/18/2009 04:41:19 AM" mode="not-after"> | |||||
<file file="${file}"/> | |||||
</cond:islastmodified> | |||||
</au:assertFalse> | |||||
<au:assertTrue> | |||||
<cond:islastmodified dateTime="08/18/2009 04:41:20 AM" mode="not-after"> | |||||
<file file="${file}"/> | |||||
</cond:islastmodified> | |||||
</au:assertTrue> | |||||
<au:assertTrue> | |||||
<cond:islastmodified dateTime="08/18/2009 04:41:21 AM" mode="not-after"> | |||||
<file file="${file}"/> | |||||
</cond:islastmodified> | |||||
</au:assertTrue> | |||||
</target> | |||||
</project> |