KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mule > impl > work > WorkerContext


1 /*
2  * $Id: WorkerContext.java 4259 2006-12-14 03:12:07Z aperepel $
3  * --------------------------------------------------------------------------------------
4  * Copyright (c) MuleSource, Inc. All rights reserved. http://www.mulesource.com
5  *
6  * The software in this package is published under the terms of the MuleSource MPL
7  * license, a copy of which has been included with this distribution in the
8  * LICENSE.txt file.
9  */

10
11 /**
12  *
13  * Copyright 2004 The Apache Software Foundation
14  *
15  * Licensed under the Apache License, Version 2.0 (the "License");
16  * you may not use this file except in compliance with the License.
17  * You may obtain a copy of the License at
18  *
19  * http://www.apache.org/licenses/LICENSE-2.0
20  *
21  * Unless required by applicable law or agreed to in writing, software
22  * distributed under the License is distributed on an "AS IS" BASIS,
23  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24  * See the License for the specific language governing permissions and
25  * limitations under the License.
26  */

27
28 package org.mule.impl.work;
29
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.mule.util.concurrent.Latch;
33
34 import javax.resource.spi.work.ExecutionContext JavaDoc;
35 import javax.resource.spi.work.Work JavaDoc;
36 import javax.resource.spi.work.WorkAdapter JavaDoc;
37 import javax.resource.spi.work.WorkCompletedException JavaDoc;
38 import javax.resource.spi.work.WorkEvent JavaDoc;
39 import javax.resource.spi.work.WorkException JavaDoc;
40 import javax.resource.spi.work.WorkListener JavaDoc;
41 import javax.resource.spi.work.WorkRejectedException JavaDoc;
42
43 /**
44  * <code>WorkerContext</code> TODO
45  */

46 public class WorkerContext implements Work JavaDoc
47 {
48
49     /**
50      * logger used by this class
51      */

52     protected static final Log logger = LogFactory.getLog(WorkerContext.class);
53
54     /**
55      * Null WorkListener used as the default WorkListener.
56      */

57     private static final WorkListener JavaDoc NULL_WORK_LISTENER = new WorkAdapter JavaDoc()
58     {
59         public void workRejected(WorkEvent JavaDoc event)
60         {
61             if (event.getException() != null)
62             {
63                 if (event.getException() instanceof WorkCompletedException JavaDoc
64                     && event.getException().getCause() != null)
65                 {
66                     logger.error(event.getWork().toString(), event.getException().getCause());
67                 }
68                 else
69                 {
70                     logger.error(event.getWork().toString(), event.getException());
71                 }
72             }
73         }
74     };
75
76     /**
77      * Priority of the thread, which will execute this work.
78      */

79     private int threadPriority;
80
81     /**
82      * Actual work to be executed.
83      */

84     private Work JavaDoc worker;
85
86     /**
87      * System.currentTimeMillis() when the wrapped Work has been accepted.
88      */

89     private long acceptedTime;
90
91     /**
92      * Number of times that the execution of this work has been tried.
93      */

94     private int retryCount;
95
96     /**
97      * Time duration (in milliseconds) within which the execution of the Work
98      * instance must start.
99      */

100     private long startTimeOut;
101
102     /**
103      * Execution context of the actual work to be executed.
104      */

105     private final ExecutionContext JavaDoc executionContext;
106
107     /**
108      * Listener to be notified during the life-cycle of the work treatment.
109      */

110     private WorkListener JavaDoc workListener = NULL_WORK_LISTENER;
111
112     /**
113      * Work exception, if any.
114      */

115     private WorkException JavaDoc workException;
116
117     /**
118      * A latch, which is released when the work is started.
119      */

120     private final Latch startLatch = new Latch();
121
122     /**
123      * A latch, which is released when the work is completed.
124      */

125     private final Latch endLatch = new Latch();
126
127     /**
128      * Create a WorkWrapper.
129      *
130      * @param work Work to be wrapped.
131      */

132     public WorkerContext(Work JavaDoc work)
133     {
134         worker = work;
135         executionContext = null;
136     }
137
138     /**
139      * Create a WorkWrapper with the specified execution context.
140      *
141      * @param aWork Work to be wrapped.
142      * @param aStartTimeout a time duration (in milliseconds) within which the
143      * execution of the Work instance must start.
144      * @param execContext an object containing the execution context with which the
145      * submitted Work instance must be executed.
146      * @param workListener an object which would be notified when the various Work
147      * processing events (work accepted, work rejected, work started,
148      */

149     public WorkerContext(Work JavaDoc aWork,
150                          long aStartTimeout,
151                          ExecutionContext JavaDoc execContext,
152                          WorkListener JavaDoc workListener)
153     {
154         worker = aWork;
155         startTimeOut = aStartTimeout;
156         executionContext = execContext;
157         if (null != workListener)
158         {
159             this.workListener = workListener;
160         }
161     }
162
163     /*
164      * (non-Javadoc)
165      *
166      * @see javax.resource.spi.work.Work#release()
167      */

168     public void release()
169     {
170         worker.release();
171     }
172
173     /**
174      * Defines the thread priority level of the thread, which will be dispatched to
175      * process this work. This priority level must be the same one for a given
176      * resource adapter.
177      *
178      * @param aPriority Priority of the thread to be used to process the wrapped Work
179      * instance.
180      */

181     public void setThreadPriority(int aPriority)
182     {
183         threadPriority = aPriority;
184     }
185
186     /**
187      * Gets the priority level of the thread, which will be dispatched to process
188      * this work. This priority level must be the same one for a given resource
189      * adapter.
190      *
191      * @return The priority level of the thread to be dispatched to process the
192      * wrapped Work instance.
193      */

194     public int getThreadPriority()
195     {
196         return threadPriority;
197     }
198
199     /**
200      * Call-back method used by a Work executor in order to notify this instance that
201      * the wrapped Work instance has been accepted.
202      *
203      * @param anObject Object on which the event initially occurred. It should be the
204      * work executor.
205      */

206     public synchronized void workAccepted(Object JavaDoc anObject)
207     {
208         // isAccepted = true;
209
acceptedTime = System.currentTimeMillis();
210         workListener.workAccepted(new WorkEvent JavaDoc(anObject, WorkEvent.WORK_ACCEPTED, worker, null));
211     }
212
213     /**
214      * System.currentTimeMillis() when the Work has been accepted. This method can be
215      * used to compute the duration of a work.
216      *
217      * @return When the work has been accepted.
218      */

219     public synchronized long getAcceptedTime()
220     {
221         return acceptedTime;
222     }
223
224     /**
225      * Gets the time duration (in milliseconds) within which the execution of the
226      * Work instance must start.
227      *
228      * @return Time out duration.
229      */

230     public long getStartTimeout()
231     {
232         return startTimeOut;
233     }
234
235     /**
236      * Used by a Work executor in order to know if this work, which should be
237      * accepted but not started has timed out. This method MUST be called prior to
238      * retry the execution of a Work.
239      *
240      * @return true if the Work has timed out and false otherwise.
241      */

242     public synchronized boolean isTimedOut()
243     {
244
245         // A value of 0 means that the work never times out.
246
// ??? really?
247
if (0 == startTimeOut || startTimeOut == MuleWorkManager.INDEFINITE)
248         {
249             return false;
250         }
251         boolean isTimeout = acceptedTime + startTimeOut > 0
252                             && System.currentTimeMillis() > acceptedTime + startTimeOut;
253         if (logger.isDebugEnabled())
254         {
255             logger.debug(this + " accepted at " + acceptedTime
256                          + (isTimeout ? " has timed out." : " has not timed out. ") + retryCount
257                          + " retries have been performed.");
258         }
259         if (isTimeout)
260         {
261             workException = new WorkRejectedException JavaDoc(this + " has timed out.", WorkException.START_TIMED_OUT);
262             workListener.workRejected(new WorkEvent JavaDoc(this, WorkEvent.WORK_REJECTED, worker, workException));
263             return true;
264         }
265         retryCount++;
266         return isTimeout;
267     }
268
269     /**
270      * Gets the WorkException, if any, thrown during the execution.
271      *
272      * @return WorkException, if any.
273      */

274     public synchronized WorkException JavaDoc getWorkException()
275     {
276         return workException;
277     }
278
279     /*
280      * (non-Javadoc)
281      *
282      * @see java.lang.Runnable#run()
283      */

284     public void run()
285     {
286         if (isTimedOut())
287         {
288             // In case of a time out, one releases the start and end latches
289
// to prevent a dead-lock.
290
startLatch.countDown();
291             endLatch.countDown();
292             return;
293         }
294         // Implementation note: the work listener is notified prior to release
295
// the start lock. This behavior is intentional and seems to be the
296
// more conservative.
297
workListener.workStarted(new WorkEvent JavaDoc(this, WorkEvent.WORK_STARTED, worker, null));
298         startLatch.countDown();
299         // Implementation note: we assume this is being called without an
300
// interesting TransactionContext,
301
// and ignore/replace whatever is associated with the current thread.
302
try
303         {
304             if (executionContext == null || executionContext.getXid() == null)
305             {
306                 // TODO currently unused, see below
307
// ExecutionContext context = new ExecutionContext();
308
try
309                 {
310                     worker.run();
311                 }
312                 finally
313                 {
314                     // ExecutionContext returningContext = new
315
// ExecutionContext();
316
// if (context != returningContext) {
317
// throw new WorkCompletedException("Wrong
318
// TransactionContext on return from work done");
319
// }
320
}
321                 // TODO should we commit the txContext to flush any leftover
322
// state???
323
}
324             else
325             {
326                 // try {
327
// long transactionTimeout =
328
// executionContext.getTransactionTimeout();
329
// //translate -1 value to 0 to indicate default transaction
330
// timeout.
331
// transactionContextManager.begin(executionContext.getXid(),
332
// transactionTimeout == -1 ? 0 : transactionTimeout);
333
// } catch (XAException e) {
334
// throw new WorkCompletedException("Transaction import failed
335
// for xid " + executionContext.getXid(),
336
// WorkCompletedException.TX_RECREATE_FAILED).initCause(e);
337
// } catch (InvalidTransactionException e) {
338
// throw new WorkCompletedException("Transaction import failed
339
// for xid " + executionContext.getXid(),
340
// WorkCompletedException.TX_RECREATE_FAILED).initCause(e);
341
// } catch (SystemException e) {
342
// throw new WorkCompletedException("Transaction import failed
343
// for xid " + executionContext.getXid(),
344
// WorkCompletedException.TX_RECREATE_FAILED).initCause(e);
345
// } catch (ImportedTransactionActiveException e) {
346
// throw new WorkCompletedException("Transaction already active
347
// for xid " + executionContext.getXid(),
348
// WorkCompletedException.TX_CONCURRENT_WORK_DISALLOWED);
349
// }
350
try
351                 {
352                     worker.run();
353                 }
354                 finally
355                 {
356                     // transactionContextManager.end(executionContext.getXid());
357
}
358
359             }
360             workListener.workCompleted(new WorkEvent JavaDoc(this, WorkEvent.WORK_COMPLETED, worker, null));
361         }
362         catch (Throwable JavaDoc e)
363         {
364             workException = (WorkException JavaDoc)(e instanceof WorkCompletedException JavaDoc
365                             ? e : new WorkCompletedException JavaDoc("Unknown error",
366                                 WorkCompletedException.UNDEFINED).initCause(e));
367             workListener.workCompleted(new WorkEvent JavaDoc(this, WorkEvent.WORK_REJECTED, worker, workException));
368         }
369         finally
370         {
371             endLatch.countDown();
372         }
373     }
374
375     /**
376      * Provides a latch, which can be used to wait the start of a work execution.
377      *
378      * @return Latch that a caller can acquire to wait for the start of a work
379      * execution.
380      */

381     public Latch provideStartLatch()
382     {
383         return startLatch;
384     }
385
386     /**
387      * Provides a latch, which can be used to wait the end of a work execution.
388      *
389      * @return Latch that a caller can acquire to wait for the end of a work
390      * execution.
391      */

392     public Latch provideEndLatch()
393     {
394         return endLatch;
395     }
396
397     public String JavaDoc toString()
398     {
399         return "Work: " + worker;
400     }
401 }
402
Popular Tags