KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > idaremedia > antx > flowcontrol > wrap > TolerantTaskSet


1 /**
2  * $Id: TolerantTaskSet.java 187 2007-03-25 17:59:16Z ssmc $
3  * Copyright 2003-2004,2007 iDare Media, Inc. All rights reserved.
4  *
5  * Originally written by iDare Media, Inc. for release into the public domain. This
6  * library, source form and binary form, is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public License as published by the
8  * Free Software Foundation; either version 2.1 of the License, or (at your option) any
9  * later version.<p>
10  *
11  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  * See the GNU LGPL (GNU Lesser General Public License) for more details.<p>
14  *
15  * You should have received a copy of the GNU Lesser General Public License along with this
16  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite
17  * 330, Boston, MA 02111-1307 USA. The LGPL can be found online at
18  * http://www.fsf.org/copyleft/lesser.html<p>
19  *
20  * This product has been influenced by several projects within the open-source community.
21  * The JWare developers wish to acknowledge the open-source community's support. For more
22  * information regarding the open-source products used within JWare, please visit the
23  * JWare website.
24  *----------------------------------------------------------------------------------------*
25  * WEBSITE- http://antxtras.sf.net/ EMAIL- jware[at]users[dot]sourceforge[dot]net
26  *----------------------------------------------------------------------------------------*
27  **/

28
29 package com.idaremedia.antx.flowcontrol.wrap;
30
31 import org.apache.tools.ant.BuildException;
32 import org.apache.tools.ant.Project;
33 import org.apache.tools.ant.Task;
34
35 import com.idaremedia.antx.FixtureOverlay;
36 import com.idaremedia.antx.ownhelpers.TaskExaminer;
37 import com.idaremedia.antx.parameters.RecoveryEnabled;
38 import com.idaremedia.antx.starters.StrictOuterTask;
39 import com.idaremedia.antx.starters.TaskSet;
40
41 /**
42  * Taskset that captures any build exception thrown by nested tasks and gives the build
43  * script an opportunity to cleanup after process-aborting build errors. Like Java-style
44  * try-catch-finally construct.
45  *
46  * @since JWare/AntX 0.3
47  * @author ssmc, &copy;2003-2004,2007 <a HREF="http://www.jware.info">iDare&nbsp;Media,&nbsp;Inc.</a>
48  * @version 0.5.1
49  * @.safety single
50  * @.group impl,helper
51  **/

52
53 public abstract class TolerantTaskSet extends TaskSet
54     implements StrictOuterTask, RecoveryEnabled, FixtureOverlay
55 {
56     /**
57      * Initializes new tolerant taskset instance.
58      **/

59     protected TolerantTaskSet(String JavaDoc iam)
60     {
61         super(iam);
62     }
63
64
65     /**
66      * Initializes new CV-labeled tolerant taskset subclass instance.
67      **/

68     protected TolerantTaskSet(String JavaDoc iam, boolean delayConfiguration)
69     {
70         super(iam, delayConfiguration);
71     }
72
73
74     /**
75      * Sets whether this taskset will continue to unwind the call
76      * stack and eventually fail with a top-level build exception.
77      * Defaults to <i>true</i>.
78      **/

79     public void setHaltIfError(boolean balk)
80     {
81         m_haltIfError = balk;
82     }
83
84
85     /**
86      * Returns <i>true</i> if this tolerant taskset will propagate
87      * any build exceptions unconditionally. <i>true</i> by default.
88      **/

89     public final boolean isHaltIfError()
90     {
91         return m_haltIfError;
92     }
93
94
95     /**
96      * Tells this task whether <em>all</em> types of runtime
97      * exceptions should be captured. Normally on build exceptions
98      * are captured.
99      * @param allRTX <i>true</i> for all types of runtime exceptions.
100      * @since JWare/AntX 0.5
101      **/

102     public void setAgainstAll(boolean allRTX)
103     {
104         m_allRTX = allRTX;
105     }
106
107
108
109     /**
110      * Returns <i>true</i> if all types of <em>runtime</em>
111      * exceptions will be captured and processed. Defaults to
112      * <i>false</i>.
113      * @since JWare/AntX 0.5
114      **/

115     public final boolean willCaptureAllRuntimeExceptions()
116     {
117         return m_allRTX;
118     }
119
120
121
122     /**
123      * Ensure the iferror and always helpers tasks are configured
124      * at same time as this task.
125      **/

126     protected void maybeConfigureSpecialTasks()
127     {
128         if (m_iferrorTask!=null) {
129             m_iferrorTask.maybeConfigure();
130         }
131         if (m_alwaysTask!=null) {
132             m_alwaysTask.maybeConfigure();
133         }
134     }
135
136
137     /**
138      * Adds a task to this tolerant taskset. If the task is one
139      * of the special helper tasks (<i>iferror</i> or <i>always</i>)
140      * it is handled specially. A tolerant taskset can have at most
141      * one of each special task. A template method that first
142      * extracts the actual task (stripping away any placeholders),
143      * calls {@linkplain #addSpecialTask addSpecialTask}, and
144      * finally calls the inherited add method if task was not special.
145      * @param task new task to be added (non-null)
146      **/

147     public void addTask(Task task)
148     {
149         require_(task!=null,"addTsk- nonzro task");
150
151         task = TaskExaminer.trueTask(task,getCOI(),this);//zap proxies!
152

153         if (!addSpecialTask(task)) {
154             super.addTask(task);
155         } else {
156             addedTask();
157         }
158     }
159
160
161     /**
162      * This taskset's special task inclusion filter method. Subclasses
163      * should extend this method to add custom processing for additional
164      * special tasks.
165      * @param task the actual task to be added (already examined)
166      * @return <i>true</i> if the task was processed as a special task
167      * @since JWare/AntX 0.4
168      **/

169     protected boolean addSpecialTask(Task task)
170     {
171         boolean wasSpecial=true;
172
173         if (task instanceof IfErrorTask) {
174             addTheIfErrorTaskset((IfErrorTask)task);
175         } else if (task instanceof AlwaysTask) {
176             addTheAlwaysTaskset((AlwaysTask)task);
177         } else {
178             wasSpecial = false;
179         }
180         return wasSpecial;
181     }
182
183
184     /**
185      * Ensures this taskset's nested tasks are executed with proper
186      * try-catch-finally protection. If neither an <i>iferror</i>
187      * nor a <i>always</i> task has been defined, this performs basically
188      * as if the tolerant wrapper didn't exist-- build errors will
189      * unwind the call stack until Ant exits the build process.
190      **/

191     protected void performNestedTasks()
192     {
193         try {
194             //perform nested tasks that can barf...
195
performTheProtectedTasksList();
196
197         } catch(RuntimeException JavaDoc rtX) {
198             //AntX 1.6+ is just wrong to do this! (ssmc)
199
if (rtX instanceof BuildException && (rtX.getCause() instanceof Error JavaDoc)) {
200                 throw (Error JavaDoc)rtX.getCause();
201             }
202
203             //iff allow all types thru do we do generic processing
204
if (!willCaptureAllRuntimeExceptions() &&
205                 !(rtX instanceof BuildException)) {
206                     throw rtX;
207             }
208
209             RuntimeException JavaDoc rethrowX;
210
211             //let iferror handler do its work!
212
if (m_iferrorTask!=null) {
213                 rethrowX = m_iferrorTask.throwOccured(rtX);
214                 m_iferrorTask.perform();
215             } else {
216                 //ensure something is recorded
217
rethrowX = recordThrowOccured(rtX);
218             }
219             //continue the unwind by default, else breakout
220
if (isHaltIfError()) {
221                 if (rethrowX!=rtX) {
222                     rethrowX.fillInStackTrace();
223                 }
224                 throw rethrowX;
225             }
226             log("'"+getTaskName()+"' consuming build exception",
227                 Project.MSG_VERBOSE);
228         } finally {
229             //do things that must always be done failure|ok
230
if (m_alwaysTask!=null) {
231                 m_alwaysTask.perform();
232             }
233         }
234     }
235
236
237     /**
238      * Called to execute this taskset's nested tasks from the protected
239      * try/catch/finally {@linkplain #performNestedTasks performNestedTasks}
240      * method. By default just calls the inherited 'performTheTasksList'.
241      * Subclasses should override this method to customize what tasks
242      * are performed. The taskset's execute conditions have already been
243      * evaluated and determined to be <i>true</i>.
244      **/

245     protected void performTheProtectedTasksList()
246         throws BuildException
247     {
248         performTheTasksList();
249     }
250
251
252
253     /**
254      * Returns this taskset's error handling helper task. Can return
255      * <i>null</i> if never defined.
256      **/

257     protected final IfErrorTask getIfErrorTaskset()
258     {
259         return m_iferrorTask;
260     }
261
262
263     /**
264      * Returns this taskset's always helper task. Can return
265      * <i>null</i> if never defined.
266      **/

267     protected final AlwaysTask getAlwaysTaskset()
268     {
269         return m_alwaysTask;
270     }
271
272
273     /**
274      * Initializes this taskset's <i>iferror</i> special task.
275      **/

276     protected final void addTheIfErrorTaskset(IfErrorTask task)
277     {
278         verifyIsUndefined_(m_iferrorTask, task);
279         task.setEnclosingTask(this);
280         m_iferrorTask = task;
281         if (task.getProject()==null) {
282             task.setProject(getProject());
283         }
284     }
285
286
287     /**
288      * Initializes this taskset's <i>always</i> special task.
289      **/

290     protected final void addTheAlwaysTaskset(AlwaysTask task)
291     {
292         verifyIsUndefined_(m_alwaysTask, task);
293         task.setEnclosingTask(this);
294         m_alwaysTask = task;
295         if (task.getProject()==null) {
296             task.setProject(getProject());
297         }
298     }
299
300
301     /**
302      * Writes a log message recording barfage.
303      * @param rtX barfage-in-question
304      * @return incoming (no substitution done)
305      **/

306     private RuntimeException JavaDoc recordThrowOccured(RuntimeException JavaDoc rtX)
307     {
308         int loglevel = Project.MSG_ERR;
309         if (!isHaltIfError()) {
310             loglevel = Project.MSG_INFO;
311         }
312         log(uistrs().get("flow.caught.failure",
313                          getOwningTarget().getName(), rtX.getMessage()),
314             loglevel);
315         return rtX;
316     }
317
318
319
320     private boolean m_haltIfError= true; //NB: unrolls and barfs by default
321
private boolean m_allRTX;//NB: only BuildExceptions by default
322
private IfErrorTask m_iferrorTask;
323     private AlwaysTask m_alwaysTask;
324
325
326     /**
327      * Controls the amount of peek-under for UnknownElement placeholders
328      * nested inside switch tasks.
329      * @since JWare/AntX 0.4
330      **/

331     private static final Class JavaDoc[] COI_= {
332         IfErrorTask.class, AlwaysTask.class
333     };
334
335
336     /**
337      * Returns a list of possible special task class names for this
338      * taskset class.
339      * @since JWare/AntX 0.4
340      **/

341     protected Class JavaDoc[] getCOI()
342     {
343         return COI_;
344     }
345 }
346
347 /* end-of-TolerantTaskSet.java */
348
Popular Tags