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. | |||
| 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 | |||
| ============================================= | |||
| @@ -1007,5 +1007,55 @@ is redundant and will be ignored.</p> | |||
| <blockquote><pre> | |||
| <hasfreespace partition="c:" needed="100M"/> | |||
| </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> | |||
| </html> | |||
| @@ -54,12 +54,12 @@ import org.apache.tools.ant.util.FileNameMapper; | |||
| */ | |||
| public class Touch extends Task { | |||
| private interface DateFormatFactory { | |||
| public interface DateFormatFactory { | |||
| DateFormat getPrimaryFormat(); | |||
| DateFormat getFallbackFormat(); | |||
| } | |||
| private static final DateFormatFactory DEFAULT_DF_FACTORY | |||
| public static final DateFormatFactory DEFAULT_DF_FACTORY | |||
| = new DateFormatFactory() { | |||
| /* | |||
| * 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: | |||
| 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 | |||
| trigger Ant's autoload of this file into namespace 'cond' (or whatever name | |||
| suits). | |||
| @@ -54,6 +54,8 @@ | |||
| classname="org.apache.tools.ant.taskdefs.condition.IsFalse"/> | |||
| <typedef name="isfileselected" onerror="ignore" | |||
| 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" | |||
| classname="org.apache.tools.ant.taskdefs.condition.IsReachable"/> | |||
| <typedef name="isreference" onerror="ignore" | |||
| @@ -86,4 +88,4 @@ | |||
| classname="org.apache.tools.ant.taskdefs.condition.TypeFound"/> | |||
| <typedef name="xor" onerror="ignore" | |||
| 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> | |||