git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@276428 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -41,10 +41,10 @@ or character data nested into the element.</p> | |||||
| <h3>Parameters specified as nested elements</h3> | <h3>Parameters specified as nested elements</h3> | ||||
| <p>As an alternative to the <i>if</i>/<i>unless</i> attributes, | <p>As an alternative to the <i>if</i>/<i>unless</i> attributes, | ||||
| conditional failure can be achieved using a single nested condition. | |||||
| For a complete list of core conditions, as well as information | |||||
| about custom conditions, see <a href="conditions.html">here</a>.<br /> | |||||
| <b>Since Ant 1.6.2</b> | |||||
| conditional failure can be achieved using a single nested | |||||
| <condition> element, which should contain exactly one | |||||
| core or custom condition. For information about conditions, see | |||||
| <a href="conditions.html">here</a>.<br /><b>Since Ant 1.6.2</b> | |||||
| </p> | </p> | ||||
| <h3>Examples</h3> | <h3>Examples</h3> | ||||
| @@ -79,12 +79,15 @@ BUILD FAILED | |||||
| build.xml:2: unless=thisdoesnotexist | build.xml:2: unless=thisdoesnotexist | ||||
| </pre> | </pre> | ||||
| A simple example using conditions to achieve the same effect: | |||||
| Using a condition to achieve the same effect: | |||||
| <pre> | <pre> | ||||
| <fail> | <fail> | ||||
| <not> | |||||
| <isset property="thisdoesnotexist"/> | |||||
| </not> | |||||
| <condition> | |||||
| <not> | |||||
| <isset property="thisdoesnotexist"/> | |||||
| </not> | |||||
| </condition> | |||||
| </fail> | </fail> | ||||
| </pre> | </pre> | ||||
| @@ -28,54 +28,87 @@ | |||||
| <target name="testNested1" description="should fail with default message"> | <target name="testNested1" description="should fail with default message"> | ||||
| <fail> | <fail> | ||||
| <and /> | |||||
| <condition> | |||||
| <and /> | |||||
| </condition> | |||||
| </fail> | </fail> | ||||
| </target> | </target> | ||||
| <target name="testNested2" description="should pass"> | <target name="testNested2" description="should pass"> | ||||
| <fail> | <fail> | ||||
| <or /> | |||||
| <condition> | |||||
| <or /> | |||||
| </condition> | |||||
| </fail> | </fail> | ||||
| </target> | </target> | ||||
| <target name="testNested3" description="should fail"> | <target name="testNested3" description="should fail"> | ||||
| <fail message="testNested3"> | <fail message="testNested3"> | ||||
| <and /> | |||||
| <condition> | |||||
| <and /> | |||||
| </condition> | |||||
| </fail> | </fail> | ||||
| </target> | </target> | ||||
| <target name="testNested4a" description="should error"> | <target name="testNested4a" description="should error"> | ||||
| <fail if="if"> | <fail if="if"> | ||||
| <and /> | |||||
| <condition> | |||||
| <and /> | |||||
| </condition> | |||||
| </fail> | </fail> | ||||
| </target> | </target> | ||||
| <target name="testNested4b" description="should error"> | <target name="testNested4b" description="should error"> | ||||
| <fail unless="unless"> | <fail unless="unless"> | ||||
| <and /> | |||||
| <condition> | |||||
| <and /> | |||||
| </condition> | |||||
| </fail> | </fail> | ||||
| </target> | </target> | ||||
| <target name="testNested4c" description="should error"> | <target name="testNested4c" description="should error"> | ||||
| <fail if="if" unless="unless"> | <fail if="if" unless="unless"> | ||||
| <and /> | |||||
| <condition> | |||||
| <and /> | |||||
| </condition> | |||||
| </fail> | </fail> | ||||
| </target> | </target> | ||||
| <target name="testNested5" description="should error"> | <target name="testNested5" description="should error"> | ||||
| <fail> | <fail> | ||||
| <and /> | |||||
| <or /> | |||||
| <condition> | |||||
| <or /> | |||||
| </condition> | |||||
| <condition> | |||||
| <and /> | |||||
| </condition> | |||||
| </fail> | </fail> | ||||
| </target> | </target> | ||||
| <target name="testNested6" description="should fail with message"> | <target name="testNested6" description="should fail with message"> | ||||
| <fail> | <fail> | ||||
| <and /> | |||||
| <condition> | |||||
| <and /> | |||||
| </condition> | |||||
| testNested6 | testNested6 | ||||
| testNested6 | testNested6 | ||||
| testNested6 | testNested6 | ||||
| </fail> | </fail> | ||||
| </target> | </target> | ||||
| <target name="testNested7a" description="should error"> | |||||
| <fail> | |||||
| <condition /> | |||||
| </fail> | |||||
| </target> | |||||
| <target name="testNested7b" description="should error"> | |||||
| <fail> | |||||
| <condition> | |||||
| <and /> | |||||
| <and /> | |||||
| </condition> | |||||
| </fail> | |||||
| </target> | |||||
| </project> | </project> | ||||
| @@ -17,6 +17,8 @@ | |||||
| package org.apache.tools.ant.taskdefs; | package org.apache.tools.ant.taskdefs; | ||||
| import java.util.Vector; | |||||
| import org.apache.tools.ant.Task; | |||||
| import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
| import org.apache.tools.ant.taskdefs.condition.Condition; | import org.apache.tools.ant.taskdefs.condition.Condition; | ||||
| import org.apache.tools.ant.taskdefs.condition.ConditionBase; | import org.apache.tools.ant.taskdefs.condition.ConditionBase; | ||||
| @@ -42,9 +44,21 @@ import org.apache.tools.ant.taskdefs.condition.ConditionBase; | |||||
| * | * | ||||
| * @ant.task name="fail" category="control" | * @ant.task name="fail" category="control" | ||||
| */ | */ | ||||
| public class Exit extends ConditionBase { | |||||
| public class Exit extends Task { | |||||
| private class NestedCondition extends ConditionBase implements Condition { | |||||
| public boolean eval() { | |||||
| if (countConditions() != 1) { | |||||
| throw new BuildException( | |||||
| "A single nested condition is required."); | |||||
| } | |||||
| return ((Condition)(getConditions().nextElement())).eval(); | |||||
| } | |||||
| } | |||||
| private String message; | private String message; | ||||
| private String ifCondition, unlessCondition; | private String ifCondition, unlessCondition; | ||||
| private NestedCondition nestedCondition; | |||||
| /** | /** | ||||
| * A message giving further information on why the build exited. | * A message giving further information on why the build exited. | ||||
| @@ -128,6 +142,19 @@ public class Exit extends ConditionBase { | |||||
| message += getProject().replaceProperties(msg); | message += getProject().replaceProperties(msg); | ||||
| } | } | ||||
| /** | |||||
| * Add a condition element. | |||||
| * @return <CODE>ConditionBase</CODE>. | |||||
| * @since Ant 1.6.2 | |||||
| */ | |||||
| public ConditionBase createCondition() { | |||||
| if (nestedCondition != null) { | |||||
| throw new BuildException("Only one nested condition is allowed."); | |||||
| } | |||||
| nestedCondition = new NestedCondition(); | |||||
| return nestedCondition; | |||||
| } | |||||
| /** | /** | ||||
| * test the if condition | * test the if condition | ||||
| * @return true if there is no if condition, or the named property exists | * @return true if there is no if condition, or the named property exists | ||||
| @@ -156,21 +183,22 @@ public class Exit extends ConditionBase { | |||||
| * @return true if there is none, or it evaluates to true | * @return true if there is none, or it evaluates to true | ||||
| */ | */ | ||||
| private boolean testNestedCondition() { | private boolean testNestedCondition() { | ||||
| if (ifCondition != null || unlessCondition != null) { | |||||
| throw new BuildException("Nested conditions " | |||||
| + "not permitted in conjunction with if/unless attributes"); | |||||
| } | |||||
| boolean result = nestedConditionPresent(); | |||||
| int count = countConditions(); | |||||
| if (count > 1) { | |||||
| throw new BuildException("Too many conditions: " + count); | |||||
| if (result && ifCondition != null || unlessCondition != null) { | |||||
| throw new BuildException("Nested conditions " | |||||
| + "not permitted in conjunction with if/unless attributes"); | |||||
| } | } | ||||
| return (count == 0) ? true | |||||
| : (((Condition)(getConditions().nextElement())).eval()); | |||||
| return result && nestedCondition.eval(); | |||||
| } | } | ||||
| /** | |||||
| * test whether there is a nested condition. | |||||
| * @return <CODE>boolean</CODE>. | |||||
| */ | |||||
| private boolean nestedConditionPresent() { | private boolean nestedConditionPresent() { | ||||
| return (countConditions() > 0); | |||||
| return (nestedCondition != null); | |||||
| } | } | ||||
| } | } | ||||
| @@ -138,7 +138,7 @@ public class FailTest extends BuildFileTest { | |||||
| public void testNested5() { | public void testNested5() { | ||||
| expectSpecificBuildException("testNested5", | expectSpecificBuildException("testNested5", | ||||
| "it is required to fail :-)", | "it is required to fail :-)", | ||||
| "Too many conditions: 2"); | |||||
| "Only one nested condition is allowed."); | |||||
| } | } | ||||
| public void testNested6() { | public void testNested6() { | ||||
| @@ -147,4 +147,17 @@ public class FailTest extends BuildFileTest { | |||||
| "testNested6\ntestNested6\ntestNested6"); | "testNested6\ntestNested6\ntestNested6"); | ||||
| } | } | ||||
| } | |||||
| public void testNested7() { | |||||
| String specificMessage = "A single nested condition is required."; | |||||
| char[] c = {'a', 'b'}; | |||||
| StringBuffer target = new StringBuffer("testNested7x"); | |||||
| for (int i = 0; i < c.length; i++) { | |||||
| target.setCharAt(target.length() - 1, c[i]); | |||||
| expectSpecificBuildException(target.toString(), | |||||
| "it is required to fail :-)", specificMessage); | |||||
| } | |||||
| } | |||||
| } | |||||