View Javadoc
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>&lt;condition&gt;</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 }