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