1
2
3
4
5
6
7 package org.mule.work;
8
9 import org.mule.RequestContext;
10 import org.mule.transaction.TransactionCoordination;
11 import org.mule.util.concurrent.Latch;
12
13 import javax.resource.spi.work.ExecutionContext;
14 import javax.resource.spi.work.Work;
15 import javax.resource.spi.work.WorkAdapter;
16 import javax.resource.spi.work.WorkCompletedException;
17 import javax.resource.spi.work.WorkEvent;
18 import javax.resource.spi.work.WorkException;
19 import javax.resource.spi.work.WorkListener;
20 import javax.resource.spi.work.WorkRejectedException;
21
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24
25
26
27
28 public class WorkerContext implements Work
29 {
30
31
32
33
34 protected static final Log logger = LogFactory.getLog(WorkerContext.class);
35
36
37
38
39 private static final WorkListener NULL_WORK_LISTENER = new WorkAdapter()
40 {
41 @Override
42 public void workRejected(WorkEvent event)
43 {
44 if (event.getException() != null)
45 {
46 if (event.getException() instanceof WorkCompletedException
47 && event.getException().getCause() != null)
48 {
49 logger.error(event.getWork().toString(), event.getException().getCause());
50 }
51 else
52 {
53 logger.error(event.getWork().toString(), event.getException());
54 }
55 }
56 }
57 };
58
59 protected ClassLoader executionClassLoader;
60
61
62
63
64 private int threadPriority;
65
66
67
68
69 private Work worker;
70
71
72
73
74 private long acceptedTime;
75
76
77
78
79 private int retryCount;
80
81
82
83
84
85 private long startTimeOut;
86
87
88
89
90 private final ExecutionContext executionContext;
91
92
93
94
95 private WorkListener workListener = NULL_WORK_LISTENER;
96
97
98
99
100 private WorkException workException;
101
102
103
104
105 private final Latch startLatch = new Latch();
106
107
108
109
110 private final Latch endLatch = new Latch();
111
112 {
113 this.executionClassLoader = Thread.currentThread().getContextClassLoader();
114 }
115
116
117
118
119
120
121 public WorkerContext(Work work)
122 {
123 worker = work;
124 executionContext = null;
125 }
126
127
128
129
130
131
132
133
134
135
136
137
138 public WorkerContext(Work aWork,
139 long aStartTimeout,
140 ExecutionContext execContext,
141 WorkListener workListener)
142 {
143 worker = aWork;
144 startTimeOut = aStartTimeout;
145 executionContext = execContext;
146 if (null != workListener)
147 {
148 this.workListener = workListener;
149 }
150 }
151
152 public void release()
153 {
154 worker.release();
155 }
156
157
158
159
160
161
162
163
164
165 public void setThreadPriority(int aPriority)
166 {
167 threadPriority = aPriority;
168 }
169
170
171
172
173
174
175
176
177
178 public int getThreadPriority()
179 {
180 return threadPriority;
181 }
182
183
184
185
186
187
188
189
190 public synchronized void workAccepted(Object anObject)
191 {
192 acceptedTime = System.currentTimeMillis();
193 workListener.workAccepted(new WorkEvent(anObject, WorkEvent.WORK_ACCEPTED, worker, null));
194 }
195
196
197
198
199
200
201
202 public synchronized long getAcceptedTime()
203 {
204 return acceptedTime;
205 }
206
207
208
209
210
211
212
213 public long getStartTimeout()
214 {
215 return startTimeOut;
216 }
217
218
219
220
221
222
223
224
225 public synchronized boolean isTimedOut()
226 {
227
228
229 if (0 == startTimeOut || startTimeOut == MuleWorkManager.INDEFINITE)
230 {
231 return false;
232 }
233 boolean isTimeout = acceptedTime + startTimeOut > 0
234 && System.currentTimeMillis() > acceptedTime + startTimeOut;
235 if (logger.isDebugEnabled())
236 {
237 logger.debug(this + " accepted at " + acceptedTime
238 + (isTimeout ? " has timed out." : " has not timed out. ") + retryCount
239 + " retries have been performed.");
240 }
241 if (isTimeout)
242 {
243 workException = new WorkRejectedException(this + " has timed out.", WorkException.START_TIMED_OUT);
244 workListener.workRejected(new WorkEvent(this, WorkEvent.WORK_REJECTED, worker, workException));
245 return true;
246 }
247 retryCount++;
248 return isTimeout;
249 }
250
251
252
253
254
255
256 public synchronized WorkException getWorkException()
257 {
258 return workException;
259 }
260
261 public void run()
262 {
263 if (isTimedOut())
264 {
265
266
267 startLatch.countDown();
268 endLatch.countDown();
269 return;
270 }
271
272
273
274 workListener.workStarted(new WorkEvent(this, WorkEvent.WORK_STARTED, worker, null));
275 startLatch.countDown();
276
277
278
279 try
280 {
281 if (executionContext == null || executionContext.getXid() == null)
282 {
283
284
285 final ClassLoader originalCl = Thread.currentThread().getContextClassLoader();
286 try
287 {
288
289 Thread.currentThread().setContextClassLoader(executionClassLoader);
290 worker.run();
291 }
292 finally
293 {
294 Thread.currentThread().setContextClassLoader(originalCl);
295
296
297
298
299
300
301
302 }
303
304
305 }
306 else
307 {
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332 try
333 {
334 worker.run();
335 }
336 finally
337 {
338
339 }
340
341 }
342 workListener.workCompleted(new WorkEvent(this, WorkEvent.WORK_COMPLETED, worker, null));
343 }
344 catch (Throwable e)
345 {
346 workException = (WorkException)(e instanceof WorkCompletedException
347 ? e : new WorkCompletedException("Unknown error",
348 WorkCompletedException.UNDEFINED).initCause(e));
349 workListener.workCompleted(new WorkEvent(this, WorkEvent.WORK_REJECTED, worker, workException));
350 }
351 finally
352 {
353 TransactionCoordination.getInstance().clear();
354 RequestContext.clear();
355 endLatch.countDown();
356 }
357 }
358
359
360
361
362
363
364
365 public Latch provideStartLatch()
366 {
367 return startLatch;
368 }
369
370
371
372
373
374
375
376 public Latch provideEndLatch()
377 {
378 return endLatch;
379 }
380
381 @Override
382 public String toString()
383 {
384 return "Work: " + worker;
385 }
386 }