KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > oddjob > jobs > IfJob


1 package org.oddjob.jobs;
2
3 import java.util.Date JavaDoc;
4
5 import org.apache.log4j.MDC;
6 import org.oddjob.Resetable;
7 import org.oddjob.Stateful;
8 import org.oddjob.Stoppable;
9 import org.oddjob.Structural;
10 import org.oddjob.framework.BasePrimary;
11 import org.oddjob.images.IconHelper;
12 import org.oddjob.logging.Log4jArchiver;
13 import org.oddjob.state.AbstractJobStateListener;
14 import org.oddjob.state.JobState;
15 import org.oddjob.state.JobStateEvent;
16 import org.oddjob.structural.ChildHelper;
17 import org.oddjob.structural.StructuralListener;
18 import org.oddjob.util.OddjobLockedException;
19
20 /**
21  * @oddjob.description
22  *
23  * This job implements an if/then/else logic. The completion state
24  * is the worst case of that of the child and the condition executed.
25  *
26  * @oddjob.example
27  *
28  * <code><pre>
29  * &lt;if name="If A File Exists"&gt;
30  * &lt;child&gt;
31  * &lt;exists file="some.txt"/&gt;
32  * &lt;/child&gt;
33  * &lt;then&gt;
34  * &lt;echo text="File Exists"/&gt;
35  * &lt;/then&gt;
36  * &lt;else&gt;
37  * &lt;echo text="File Doesn't Exist"/&gt;
38  * &lt;/else&gt;
39  * &lt;exception&gt;
40  * &lt;echo text="Big Problem"/&gt;
41  * &lt;/exception&gt;
42  * &lt;/if&gt;
43  * </pre></code>
44  *
45  * @author Rob Gordon
46  */

47
48
49 public class IfJob extends BasePrimary
50         implements Runnable JavaDoc, Stateful, Resetable, Structural, Stoppable {
51     private static final long serialVersionUID = 20050806;
52
53     private boolean initialised;
54     
55     /**
56      * @oddjob.element child
57      * @oddjob.description The child job, on who's completion
58      * state the execution of the branches is decided.
59      * @oddjob.required Yes.
60      */

61     private transient Runnable JavaDoc childJob;
62
63     /**
64      * @oddjob.element then
65      * @oddjob.description Executed if the state
66      * of the child job is complete.
67      * @oddjob.required No.
68      */

69     private transient Runnable JavaDoc thenJob;
70     
71     /**
72      * @oddjob.element else
73      * @oddjob.description Executed if the state
74      * of the child job is not complete.
75      * @oddjob.required No.
76      */

77     private transient Runnable JavaDoc elseJob;
78
79
80     /**
81      * @oddjob.element exception
82      * @oddjob.description Executed if the state
83      * of the child job is exception.
84      * @oddjob.required No.
85      */

86     private transient Runnable JavaDoc exceptionJob;
87
88     private transient ChildHelper childHelper = new ChildHelper(this);
89     
90     // ignore the child when we're executing
91
private transient volatile boolean executingChild;
92     
93     private transient JobStateEvent lastChildEvent;
94     private transient JobStateEvent lastDependantEvent;
95
96     class ChildListener extends AbstractJobStateListener {
97         protected void jobStateReady(Stateful source, Date JavaDoc time) {
98             lastChildEvent = new JobStateEvent(
99                     IfJob.this, JobState.READY, time, null);
100             if (executingChild) {
101                 return;
102             }
103             fireJobStateEvent(lastChildEvent);
104         }
105         
106         protected void jobStateComplete(Stateful source, Date JavaDoc time) {
107             lastChildEvent = new JobStateEvent(
108                     IfJob.this, JobState.COMPLETE, time, null);
109             if (executingChild) {
110                 return;
111             }
112             if (lastDependantEvent == null) {
113                 // for the situation where there is no dependents.
114
fireJobStateEvent(lastChildEvent);
115             }
116             else {
117                 fireJobStateEvent(lastDependantEvent);
118             }
119         }
120         
121         protected void jobStateNotComplete(Stateful source, Date JavaDoc time) {
122             lastChildEvent = new JobStateEvent(
123                     IfJob.this, JobState.NOT_COMPLETE, time, null);
124             if (executingChild) {
125                 return;
126             }
127             if (lastDependantEvent.getJobState() == JobState.EXCEPTION) {
128                 if (lastDependantEvent == null) {
129                     // for the situation where there is no dependents.
130
fireJobStateEvent(lastChildEvent);
131                 }
132                 else {
133                     fireJobStateEvent(lastDependantEvent);
134                 }
135             } else {
136                 fireJobStateEvent(lastChildEvent);
137             }
138         }
139         protected void jobStateException(Stateful source, Date JavaDoc time, Throwable JavaDoc throwable) {
140             lastChildEvent = new JobStateEvent(
141                     IfJob.this, JobState.EXCEPTION, time, throwable);
142             if (executingChild) {
143                 return;
144             }
145             fireJobStateEvent(lastChildEvent);
146         }
147     }
148     
149     private transient ChildListener childListener;
150     
151     class DependentListener extends AbstractJobStateListener {
152         protected void jobStateReady(Stateful source, Date JavaDoc time) {
153             lastDependantEvent = new JobStateEvent(
154                     IfJob.this, JobState.READY, time, null);
155             fireJobStateEvent(lastDependantEvent);
156         }
157         
158         protected void jobStateComplete(Stateful source, Date JavaDoc time) {
159             lastDependantEvent = new JobStateEvent(
160                     IfJob.this, JobState.COMPLETE, time, null);
161             fireJobStateEvent(lastChildEvent);
162         }
163         
164         protected void jobStateNotComplete(Stateful source, Date JavaDoc time) {
165             lastDependantEvent = new JobStateEvent(
166                     IfJob.this, JobState.NOT_COMPLETE, time, null);
167             if (lastChildEvent.getJobState() == JobState.EXCEPTION) {
168                 fireJobStateEvent(lastChildEvent);
169             } else {
170                 fireJobStateEvent(lastDependantEvent);
171             }
172         }
173         protected void jobStateException(Stateful source, Date JavaDoc time, Throwable JavaDoc throwable) {
174             lastDependantEvent = new JobStateEvent(
175                     IfJob.this, JobState.EXCEPTION, time, throwable);
176             fireJobStateEvent(lastDependantEvent);
177         }
178     }
179
180     private transient DependentListener thenListener;
181     private transient DependentListener elseListener;
182     private transient DependentListener exceptionListener;
183     
184     /**
185      * Add child.
186      *
187      * @param child The child job.
188      */

189     public void addComponentChild(Runnable JavaDoc child)
190     throws ClassCastException JavaDoc {
191         childJob = child;
192         childListener = new ChildListener();
193         ((Stateful) childJob).addJobStateListener(childListener);
194     }
195     
196     /**
197      * Add then.
198      *
199      * @param then The then job.
200      */

201     public void addComponentThen(Runnable JavaDoc then) {
202         thenJob = then;
203         thenListener = new DependentListener();
204         ((Stateful) thenJob).addJobStateListener(thenListener);
205     }
206
207     /**
208      * Add else.
209      *
210      * @param elze The else job.
211      */

212     public void addComponentElse(Runnable JavaDoc elze) {
213         elseJob = elze;
214         elseListener = new DependentListener();
215         ((Stateful) elseJob).addJobStateListener(elseListener);
216     }
217
218     /**
219      * Add exception.
220      *
221      * @param exception The exception.
222      */

223     public void addComponentException(Runnable JavaDoc exception) {
224         exceptionJob = exception;
225         exceptionListener = new DependentListener();
226         ((Stateful) exceptionJob).addJobStateListener(exceptionListener);
227     }
228     
229     /**
230      * Initialize.
231      */

232     public void init() {
233         if (childJob == null) {
234             throw new IllegalStateException JavaDoc("A child job is required.");
235         }
236         childHelper.addChild(childJob);
237         if (thenJob != null) {
238             childHelper.addChild(thenJob);
239         }
240         if (elseJob != null) {
241             childHelper.addChild(elseJob);
242         }
243         if (exceptionJob != null) {
244             childHelper.addChild(exceptionJob);
245         }
246         initialised = true;
247     }
248
249     public final void run() throws OddjobLockedException {
250         if (!initialised) {
251             throw new IllegalStateException JavaDoc("Not initialised - remeber to call init()");
252         }
253         lock.accquire("Job executing.");
254         String JavaDoc oldMDC = (String JavaDoc)MDC.get(Log4jArchiver.MDC);
255         try {
256             MDC.put(Log4jArchiver.MDC, getLogger());
257             if (!stateHandler.requestJobStateExecuting()) {
258                 logger().debug("Can't execute job [" + this + "] because state is ["
259                         + stateHandler.getJobState() + "]");
260                 return;
261             }
262             iconHelper.changeIcon(IconHelper.EXECUTING);
263     
264             // runtime configuration.
265
if (!configure()) {
266                 return;
267             }
268             logger().info("Executing job [" + this + "]");
269             try {
270                 execute();
271             }
272             catch (Throwable JavaDoc e) {
273                 logger().warn("Job Exception in [" + this + "]", e);
274                 setJobStateException(e);
275                 return;
276             }
277     
278             logger().debug("Finished job [" + this + "]");
279         }
280         finally {
281             if (oldMDC != null) {
282                 MDC.put(Log4jArchiver.MDC, oldMDC);
283             }
284             else {
285                 MDC.remove(Log4jArchiver.MDC);
286             }
287             lock.release();
288         }
289     }
290         
291     protected void execute() {
292         
293         executingChild = true;
294         try {
295             childJob.run();
296         } finally {
297             executingChild = false;
298         }
299         
300         JobState jobState = lastChildEvent.getJobState();
301         if (jobState == JobState.COMPLETE) {
302             if (thenJob != null) {
303                 thenJob.run();
304             }
305             else {
306                 fireJobStateEvent(lastChildEvent);
307             }
308         }
309         else if (jobState == JobState.NOT_COMPLETE) {
310             if (elseJob != null) {
311                 elseJob.run();
312             }
313             else {
314                 fireJobStateEvent(lastChildEvent);
315             }
316         }
317         else if (jobState == JobState.EXCEPTION) {
318             if (exceptionJob != null) {
319                 exceptionJob.run();
320             }
321             else {
322                 fireJobStateEvent(lastChildEvent);
323             }
324         }
325     }
326     
327     /**
328      * Fire the new job state.
329      *
330      * @param event The event.
331      */

332     protected void fireJobStateEvent(JobStateEvent event) {
333         stateHandler.fireEvent(event);
334         JobState jobState = event.getJobState();
335         if (jobState == JobState.READY) {
336             iconHelper.changeIcon(IconHelper.READY);
337             logger().info("Job [" + this + "] Ready.");
338         }
339         else if (jobState == JobState.COMPLETE) {
340             iconHelper.changeIcon(IconHelper.COMPLETE);
341             logger().info("Job [" + this + "] Complete.");
342         }
343         else if (jobState == JobState.NOT_COMPLETE) {
344             iconHelper.changeIcon(IconHelper.NOT_COMPLETE);
345             logger().info("Job [" + this + "] Not Complete.");
346         }
347         else if (jobState == JobState.EXCEPTION) {
348             iconHelper.changeIcon(IconHelper.EXCEPTION);
349             logger().warn("Job [" + this + "] Exception.",
350                     event.getException());
351         }
352     }
353     
354     /**
355      * Perform a soft reset on the job.
356      */

357     public void softReset() {
358         if (childJob instanceof Resetable) {
359             ((Resetable) childJob).softReset();
360         }
361         if (thenJob != null && thenJob instanceof Resetable) {
362             ((Resetable) thenJob).hardReset();
363         }
364         if (elseJob != null && elseJob instanceof Resetable) {
365             ((Resetable) elseJob).hardReset();
366         }
367         if (exceptionJob != null && exceptionJob instanceof Resetable) {
368             ((Resetable) exceptionJob).hardReset();
369         }
370     }
371     
372     public void stop() {
373         if (destroyed) {
374             throw new IllegalStateException JavaDoc("[" + this + "] destroyed");
375         }
376         logger().debug("Thread [" + Thread.currentThread().getName()
377                 + "] requested [" + getName() + "] stop.");
378         
379         if (iconHelper.currentId()== IconHelper.EXECUTING) {
380             iconHelper.changeIcon(IconHelper.STOPPING);
381         }
382         
383         stop = true;
384         childHelper.stopChildren();
385         
386         synchronized (this) {
387             notifyAll();
388         }
389     }
390     
391     /**
392      * Perform a hard reset on the job.
393      */

394     public void hardReset() {
395         childHelper.hardResetChildren();
396     }
397
398     /**
399      * Add a listener. The listener will immediately recieve add
400      * notifications for all existing children.
401      *
402      * @param listener The listener.
403      */

404     public void addStructuralListener(StructuralListener listener) {
405         if (destroyed) {
406             throw new IllegalStateException JavaDoc("[" + this + "] destroyed");
407         }
408         childHelper.addStructuralListener(listener);
409     }
410     
411     /**
412      * Remove a listener.
413      *
414      * @param listener The listner.
415      */

416     public void removeStructuralListener(StructuralListener listener) {
417         childHelper.removeStructuralListener(listener);
418     }
419     
420     public void onDestroy() {
421         if (thenJob != null) {
422             ((Stateful) thenJob).removeJobStateListener(thenListener);
423         }
424         if (elseJob != null) {
425             ((Stateful) elseJob).removeJobStateListener(elseListener);
426         }
427         if (exceptionJob != null) {
428             ((Stateful) exceptionJob).removeJobStateListener(exceptionListener);
429         }
430         ((Stateful)childJob).removeJobStateListener(childListener);
431         childHelper.destroyAll();
432     }
433 }
434
435
Popular Tags