1 /*
2 * (C) Copyright 2014 Nuxeo SA (http://nuxeo.com/) and contributors.
3 *
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the GNU Lesser General Public License
6 * (LGPL) version 2.1 which accompanies this distribution, and is available at
7 * http://www.gnu.org/licenses/lgpl-2.1.html
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * Contributors:
15 * Julien Carsique
16 *
17 */
18
19 package org.nuxeo.build.ant;
20
21 import java.util.Hashtable;
22
23 import org.apache.tools.ant.BuildException;
24 import org.apache.tools.ant.ExitStatusException;
25 import org.apache.tools.ant.Project;
26 import org.apache.tools.ant.Target;
27 import org.apache.tools.ant.Task;
28 import org.apache.tools.ant.UnknownElement;
29 import org.apache.tools.ant.taskdefs.Exit;
30 import org.apache.tools.ant.taskdefs.condition.Condition;
31
32 /**
33 * Similar to {@link Exit} but allows to successfully end the build
34 *
35 * Exits the active build, giving an additional message
36 * if available.
37 *
38 * The <code>if</code> and <code>unless</code> attributes make the
39 * exit conditional -both probe for the named property being defined.
40 * The <code>if</code> tests for the property being defined, the
41 * <code>unless</code> for a property being undefined.
42 *
43 * If both attributes are set, then the task exits only if both tests
44 * are true. i.e.
45 *
46 * <pre>
47 * exit := defined(ifProperty) && !defined(unlessProperty)
48 * </pre>
49 *
50 * A single nested<code><condition></code> element can be specified
51 * instead of using <code>if</code>/<code>unless</code> (a combined
52 * effect can be achieved using <code>isset</code> conditions).
53 *
54 * @ant.task name="exit" category="control"
55 * @since 2.0.3
56 */
57 public class ExitTask extends Exit {
58
59 private final class False implements Condition {
60 @Override
61 public boolean eval() throws BuildException {
62 return false;
63 }
64 }
65
66 private False falseCondition = new False();
67
68 @Override
69 /**
70 * Throw a <code>BuildException</code> to exit (fail) the build if {@code status!=0}.
71 * If specified, evaluate conditions:
72 * A single nested condition is accepted, but requires that the
73 * <code>if</code>/<code>unless</code> attributes be omitted.
74 * If the nested condition evaluates to true, or the
75 * ifCondition is true or unlessCondition is false, the build will exit.
76 *
77 * The exit message is constructed from the text fields, from
78 * the nested condition (if specified), or finally from
79 * the if and unless parameters (if present).
80 * @throws BuildException on error
81 */
82 public void execute() throws BuildException {
83 String exitMsg = null;
84 try {
85 super.execute();
86 // No raised error => condition failed, no exit
87 return;
88 } catch (ExitStatusException e) {
89 if (e.getStatus() > 0) {
90 throw e;
91 } else {
92 exitMsg = e.getMessage();
93 }
94 } catch (BuildException e) {
95 exitMsg = e.getMessage();
96 }
97 exit(exitMsg);
98 }
99
100 protected void exit(String message) {
101 Task doNothing = new Task() {
102 };
103 getProject().log(message, Project.MSG_INFO);
104 Target owningTarget = getOwningTarget();
105 Hashtable<String, Target> targets = getProject().getTargets();
106 for (Target eachTarget : targets.values()) {
107 eachTarget.setIf(falseCondition);
108 if (eachTarget == owningTarget) {
109 for (Task task : eachTarget.getTasks()) {
110 getProject().log("Invalidating tasks from " + eachTarget,
111 Project.MSG_DEBUG);
112 try {
113 if (task instanceof UnknownElement) {
114 UnknownElement currentTask = (UnknownElement) task;
115 if (currentTask.getRealThing() == this) {
116 continue;
117 }
118 getProject().log(
119 "Invalidated " + currentTask.getTaskName(),
120 Project.MSG_DEBUG);
121 currentTask.setRealThing(doNothing);
122 } else {
123 getProject().log(
124 "Not an UnknownElement: "
125 + task.getTaskName(),
126 Project.MSG_DEBUG);
127 }
128 } catch (SecurityException | IllegalArgumentException e) {
129 throw new BuildException(e);
130 }
131 }
132 }
133 }
134 }
135
136 }