1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.jelly.tags.threads;
17
18 import org.apache.commons.logging.Log;
19 import org.apache.commons.logging.LogFactory;
20
21 /***
22 * Adds some functionality to the jdk thread class.
23 *
24 * @author <a href="mailto:jason@jhorman.org">Jason Horman</a>
25 */
26
27 public class JellyThread extends Thread {
28 /*** The Log to which logging calls will be made. */
29 private static final Log log = LogFactory.getLog(ThreadTag.class);
30
31 /*** While this thread is still running it owns this mutex */
32 private Mutex runningMutex = new Mutex();
33 /*** The Runnable target */
34 private Runnable target = null;
35
36 /*** Tracks the status of this thread */
37 RunnableStatus status = new RunnableStatus();
38
39 public JellyThread() {
40
41 while (true) {
42 try {
43 runningMutex.acquire();
44 break;
45 } catch (InterruptedException e) {
46 }
47 }
48 }
49
50 /***
51 * Set the Runnable target that will be run
52 */
53 public void setTarget(Runnable target) {
54 this.target = target;
55 }
56
57 /***
58 * Run the thread
59 */
60 public void run() {
61 log.debug("Starting thread \"" + getName() + "\"");
62
63
64 try {
65
66 log.debug("Thread \"" + getName() + "\" running");
67 target.run();
68
69
70 status.set(RunnableStatus.SUCCESS);
71
72 } catch(RequirementException e) {
73
74 status.set(RunnableStatus.AVOIDED);
75 log.warn("Thread \"" + getName() + "\" avoided, " + e.getMessage());
76
77 } catch(TimeoutException e) {
78
79 status.set(RunnableStatus.AVOIDED);
80 log.warn("Thread \"" + getName() + "\" avoided, " + e.getMessage());
81
82 } catch (Exception e) {
83
84
85 status.set(RunnableStatus.FAILURE, e);
86 log.error("Thread \"" + getName() + "\" failure, " + e.getMessage());
87 log.debug(e);
88
89 }
90
91
92 runningMutex.release();
93
94 log.debug("Thread \"" + getName() + "\" finished");
95 }
96
97 /***
98 * Call this method from a different thread to wait until this thread is done. This
99 * is used by the {@link WaitForTag} class.
100 */
101 public void waitUntilDone(long howLong) throws TimeoutException {
102 if (Thread.currentThread() == this) {
103 throw new RuntimeException("This method should be called from a different thread than itself");
104 }
105
106
107 while (true) {
108 try {
109 if (howLong == -1) {
110 runningMutex.acquire();
111 break;
112 } else if (!runningMutex.attempt(howLong)) {
113 throw new TimeoutException("max wait time exceeded");
114 }
115 } catch (InterruptedException e) {
116 }
117 }
118
119
120 runningMutex.release();
121 }
122
123 /*** Get the status of this thread */
124 public RunnableStatus getStatus() {
125 return status;
126 }
127 }