1 /*
2 * JBoss, Home of Professional Open Source.
3 * Copyright 2006, Red Hat Middleware LLC, and individual contributors
4 * as indicated by the @author tags. See the copyright.txt file in the
5 * distribution for a full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */
22 package org.jboss.resource.work;
23
24 import javax.resource.spi.work.ExecutionContext;
25 import javax.resource.spi.work.Work;
26 import javax.resource.spi.work.WorkCompletedException;
27 import javax.resource.spi.work.WorkEvent;
28 import javax.resource.spi.work.WorkException;
29 import javax.resource.spi.work.WorkListener;
30 import javax.resource.spi.work.WorkManager;
31 import javax.resource.spi.work.WorkRejectedException;
32
33 import org.jboss.logging.Logger;
34 import org.jboss.util.JBossStringBuilder;
35 import org.jboss.util.NestedRuntimeException;
36 import org.jboss.util.threadpool.BasicTaskWrapper;
37 import org.jboss.util.threadpool.StartTimeoutException;
38 import org.jboss.util.threadpool.Task;
39
40 /**
41 * Wraps the resource adapter's work.
42 *
43 * @author <a href="mailto:adrian@jboss.org">Adrian Brock</a>
44 * @version $Revision: 71538 $
45 */
46 public class WorkWrapper extends BasicTaskWrapper implements Task
47 {
48 /** The log */
49 private static final Logger log = Logger.getLogger(WorkWrapper.class);
50
51 /** Whether we are tracing */
52 private boolean trace = log.isTraceEnabled();
53
54 /** The work */
55 private Work work;
56
57 /** The execution context */
58 private ExecutionContext executionContext;
59
60 /** the work listener */
61 private WorkListener workListener;
62
63 /** The start timeout */
64 private long startTimeout;
65
66 /** The work manager */
67 private JBossWorkManager workManager;
68
69 /** The wait type */
70 private int waitType;
71
72 /** The blocked time */
73 private long blockedTime;
74
75 /** Any exception */
76 private WorkException exception;
77
78 /**
79 * Create a new WorkWrapper
80 *
81 * @param workManager the work manager
82 * @param work the work
83 * @param waitType the waitType
84 * @param executionContext the execution context
85 * @param workListener the WorkListener
86 * @throws IllegalArgumentException for null work, execution context or a negative start timeout
87 */
88 public WorkWrapper(JBossWorkManager workManager, Work work, int waitType, long startTimeout, ExecutionContext executionContext, WorkListener workListener)
89 {
90 super();
91
92 if (work == null)
93 throw new IllegalArgumentException("Null work");
94 if (executionContext == null)
95 throw new IllegalArgumentException("Null execution context");
96 if (startTimeout < 0)
97 throw new IllegalArgumentException("Illegal start timeout: " + startTimeout);
98
99 this.workManager = workManager;
100 this.work = work;
101 this.waitType = waitType;
102 this.startTimeout = startTimeout;
103 this.executionContext = executionContext;
104 this.workListener = workListener;
105
106 setTask(this);
107 }
108
109 /**
110 * Get the work manager
111 *
112 * @return the work manager
113 */
114 public JBossWorkManager getWorkManager()
115 {
116 return workManager;
117 }
118
119 /**
120 * Retrieve the work
121 *
122 * @return the work
123 */
124 public Work getWork()
125 {
126 return work;
127 }
128
129 /**
130 * Retrieve the work listener
131 *
132 * @return the WorkListener
133 */
134 public WorkListener getWorkListener()
135 {
136 return workListener;
137 }
138
139 /**
140 * Retrieve the exection context
141 *
142 * @return the execution context
143 */
144 public ExecutionContext getExecutionContext()
145 {
146 return executionContext;
147 }
148
149 /**
150 * Retrieve the time blocked
151 *
152 * @return the blocked time
153 */
154 public long getBlockedElapsed()
155 {
156 return blockedTime;
157 }
158
159 /**
160 * Get any exception
161 *
162 * @return the exception or null if there is none
163 */
164 public WorkException getWorkException()
165 {
166 return exception;
167 }
168
169 public int getWaitType()
170 {
171 return waitType;
172 }
173
174 public int getPriority()
175 {
176 return Thread.NORM_PRIORITY;
177 }
178
179 public long getStartTimeout()
180 {
181 return startTimeout;
182 }
183
184 public long getCompletionTimeout()
185 {
186 return executionContext.getTransactionTimeout();
187 }
188
189 public void execute()
190 {
191 if (trace)
192 log.trace("Executing work " + this);
193 try
194 {
195 workManager.startWork(this);
196 }
197 catch (WorkException e)
198 {
199 taskRejected(new NestedRuntimeException(e));
200 return;
201 }
202 try
203 {
204 work.run();
205 }
206 finally
207 {
208 workManager.endWork(this);
209 }
210 if (trace)
211 log.trace("Executed work " + this);
212 }
213
214 public void stop()
215 {
216 if (trace)
217 log.trace("Stopping work " + this);
218
219 work.release();
220 }
221
222 public void accepted(long time)
223 {
224 blockedTime = time;
225
226 if (trace)
227 log.trace("Accepted work " + this);
228
229 if (workListener != null)
230 {
231 WorkEvent event = new WorkEvent(workManager, WorkEvent.WORK_ACCEPTED, work, null);
232 workListener.workAccepted(event);
233 }
234 }
235
236 public void rejected(long time, Throwable throwable)
237 {
238 blockedTime = time;
239
240 if (trace)
241 {
242 if (throwable != null)
243 log.trace("Rejecting work " + this, throwable);
244 else
245 log.trace("Rejecting work " + this);
246 }
247
248 if (throwable != null)
249 {
250 exception = new WorkRejectedException(throwable);
251 if (throwable instanceof StartTimeoutException)
252 exception.setErrorCode(WorkRejectedException.START_TIMED_OUT);
253 }
254
255 workManager.cancelWork(this);
256
257 if (workListener != null)
258 {
259 WorkEvent event = new WorkEvent(workManager, WorkEvent.WORK_ACCEPTED, work, exception);
260 workListener.workRejected(event);
261 }
262 }
263
264 public void started(long time)
265 {
266 if (waitType != WAIT_NONE)
267 blockedTime = time;
268
269 if (workListener != null)
270 {
271 WorkEvent event = new WorkEvent(workManager, WorkEvent.WORK_STARTED, work, null);
272 workListener.workStarted(event);
273 }
274 }
275
276 public void completed(long time, Throwable throwable)
277 {
278 if (waitType == WAIT_FOR_COMPLETE)
279 blockedTime = time;
280
281 if (throwable != null)
282 exception = new WorkCompletedException(throwable);
283
284 if (trace)
285 log.trace("Completed work " + this);
286
287 if (workListener != null)
288 {
289 WorkEvent event = new WorkEvent(workManager, WorkEvent.WORK_COMPLETED, work, exception);
290 workListener.workCompleted(event);
291 }
292 }
293
294 public String toString()
295 {
296 JBossStringBuilder buffer = new JBossStringBuilder(100);
297 buffer.append("WorkWrapper@").append(Integer.toHexString(System.identityHashCode(this)));
298 buffer.append("[workManger=").append(workManager);
299 buffer.append(" work=").append(work);
300 buffer.append(" state=").append(getStateString());
301 if (executionContext != null && executionContext.getXid() != null)
302 {
303 buffer.append(" xid=").append(executionContext.getXid());
304 buffer.append(" txTimeout=").append(executionContext.getTransactionTimeout());
305 }
306 buffer.append(" waitType=");
307 switch (waitType)
308 {
309 case WAIT_NONE:
310 {
311 buffer.append("WAIT_NONE");
312 break;
313 }
314 case WAIT_FOR_START:
315 {
316 buffer.append("WAIT_FOR_START");
317 break;
318 }
319 case WAIT_FOR_COMPLETE:
320 {
321 buffer.append("WAIT_FOR_COMPLETE");
322 break;
323 }
324 default:
325 buffer.append("???");
326 }
327 if (startTimeout != WorkManager.INDEFINITE)
328 buffer.append(" startTimeout=").append(startTimeout);
329 long completionTimeout = getCompletionTimeout();
330 if (completionTimeout != -1)
331 buffer.append(" completionTimeout=").append(completionTimeout);
332 if (blockedTime != 0)
333 buffer.append(" blockTime=").append(blockedTime);
334 buffer.append(" elapsedTime=").append(getElapsedTime());
335 if (workListener != null)
336 buffer.append(" workListener=").append(workListener);
337 if (exception != null)
338 buffer.append(" exception=").append(exception);
339 buffer.append("]");
340 return buffer.toString();
341 }
342 }