001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.resource.work;
023:
024: import javax.resource.spi.work.ExecutionContext;
025: import javax.resource.spi.work.Work;
026: import javax.resource.spi.work.WorkCompletedException;
027: import javax.resource.spi.work.WorkEvent;
028: import javax.resource.spi.work.WorkException;
029: import javax.resource.spi.work.WorkListener;
030: import javax.resource.spi.work.WorkManager;
031: import javax.resource.spi.work.WorkRejectedException;
032:
033: import org.jboss.logging.Logger;
034: import org.jboss.util.JBossStringBuilder;
035: import org.jboss.util.NestedRuntimeException;
036: import org.jboss.util.threadpool.BasicTaskWrapper;
037: import org.jboss.util.threadpool.StartTimeoutException;
038: import org.jboss.util.threadpool.Task;
039:
040: /**
041: * Wraps the resource adapter's work.
042: *
043: * @author <a href="mailto:adrian@jboss.org">Adrian Brock</a>
044: * @version $Revision: 57189 $
045: */
046: public class WorkWrapper extends BasicTaskWrapper implements Task {
047: /** The log */
048: private static final Logger log = Logger
049: .getLogger(WorkWrapper.class);
050:
051: /** Whether we are tracing */
052: private boolean trace = log.isTraceEnabled();
053:
054: /** The work */
055: private Work work;
056:
057: /** The execution context */
058: private ExecutionContext executionContext;
059:
060: /** the work listener */
061: private WorkListener workListener;
062:
063: /** The start timeout */
064: private long startTimeout;
065:
066: /** The work manager */
067: private JBossWorkManager workManager;
068:
069: /** The wait type */
070: private int waitType;
071:
072: /** The blocked time */
073: private long blockedTime;
074:
075: /** Any exception */
076: private WorkException exception;
077:
078: /**
079: * Create a new WorkWrapper
080: *
081: * @param workManager the work manager
082: * @param work the work
083: * @param waitType the waitType
084: * @param executionContext the execution context
085: * @param workListener the WorkListener
086: * @throws IllegalArgumentException for null work, execution context or a negative start timeout
087: */
088: public WorkWrapper(JBossWorkManager workManager, Work work,
089: int waitType, long startTimeout,
090: ExecutionContext executionContext, WorkListener workListener) {
091: super ();
092:
093: if (work == null)
094: throw new IllegalArgumentException("Null work");
095: if (executionContext == null)
096: throw new IllegalArgumentException("Null execution context");
097: if (startTimeout < 0)
098: throw new IllegalArgumentException(
099: "Illegal start timeout: " + startTimeout);
100:
101: this .workManager = workManager;
102: this .work = work;
103: this .waitType = waitType;
104: this .startTimeout = startTimeout;
105: this .executionContext = executionContext;
106: this .workListener = workListener;
107:
108: setTask(this );
109: }
110:
111: /**
112: * Get the work manager
113: *
114: * @return the work manager
115: */
116: public JBossWorkManager getWorkManager() {
117: return workManager;
118: }
119:
120: /**
121: * Retrieve the work
122: *
123: * @return the work
124: */
125: public Work getWork() {
126: return work;
127: }
128:
129: /**
130: * Retrieve the work listener
131: *
132: * @return the WorkListener
133: */
134: public WorkListener getWorkListener() {
135: return workListener;
136: }
137:
138: /**
139: * Retrieve the exection context
140: *
141: * @return the execution context
142: */
143: public ExecutionContext getExecutionContext() {
144: return executionContext;
145: }
146:
147: /**
148: * Retrieve the time blocked
149: *
150: * @return the blocked time
151: */
152: public long getBlockedElapsed() {
153: return blockedTime;
154: }
155:
156: /**
157: * Get any exception
158: *
159: * @return the exception or null if there is none
160: */
161: public WorkException getWorkException() {
162: return exception;
163: }
164:
165: public int getWaitType() {
166: return waitType;
167: }
168:
169: public int getPriority() {
170: return Thread.NORM_PRIORITY;
171: }
172:
173: public long getStartTimeout() {
174: return startTimeout;
175: }
176:
177: public long getCompletionTimeout() {
178: return executionContext.getTransactionTimeout();
179: }
180:
181: public void execute() {
182: if (trace)
183: log.trace("Executing work " + this );
184: try {
185: workManager.startWork(this );
186: } catch (WorkException e) {
187: taskRejected(new NestedRuntimeException(e));
188: return;
189: }
190: try {
191: work.run();
192: } finally {
193: workManager.endWork(this );
194: }
195: if (trace)
196: log.trace("Executed work " + this );
197: }
198:
199: public void stop() {
200: if (trace)
201: log.trace("Stopping work " + this );
202:
203: work.release();
204: }
205:
206: public void accepted(long time) {
207: blockedTime = time;
208:
209: if (trace)
210: log.trace("Accepted work " + this );
211:
212: if (workListener != null) {
213: WorkEvent event = new WorkEvent(workManager,
214: WorkEvent.WORK_ACCEPTED, work, null);
215: workListener.workAccepted(event);
216: }
217: }
218:
219: public void rejected(long time, Throwable throwable) {
220: blockedTime = time;
221:
222: if (trace) {
223: if (throwable != null)
224: log.trace("Rejecting work " + this , throwable);
225: else
226: log.trace("Rejecting work " + this );
227: }
228:
229: if (throwable != null) {
230: exception = new WorkRejectedException(throwable);
231: if (throwable instanceof StartTimeoutException)
232: exception
233: .setErrorCode(WorkRejectedException.START_TIMED_OUT);
234: }
235:
236: workManager.cancelWork(this );
237:
238: if (workListener != null) {
239: WorkEvent event = new WorkEvent(workManager,
240: WorkEvent.WORK_ACCEPTED, work, exception);
241: workListener.workRejected(event);
242: }
243: }
244:
245: public void started(long time) {
246: if (waitType != WAIT_NONE)
247: blockedTime = time;
248:
249: if (workListener != null) {
250: WorkEvent event = new WorkEvent(workManager,
251: WorkEvent.WORK_STARTED, work, null);
252: workListener.workStarted(event);
253: }
254: }
255:
256: public void completed(long time, Throwable throwable) {
257: if (waitType == WAIT_FOR_COMPLETE)
258: blockedTime = time;
259:
260: if (throwable != null)
261: exception = new WorkCompletedException(throwable);
262:
263: if (trace)
264: log.trace("Completed work " + this );
265:
266: if (workListener != null) {
267: WorkEvent event = new WorkEvent(workManager,
268: WorkEvent.WORK_COMPLETED, work, exception);
269: workListener.workCompleted(event);
270: }
271: }
272:
273: public String toString() {
274: JBossStringBuilder buffer = new JBossStringBuilder(100);
275: buffer.append("WorkWrapper@").append(
276: Integer.toHexString(System.identityHashCode(this )));
277: buffer.append("[workManger=").append(workManager);
278: buffer.append(" work=").append(work);
279: buffer.append(" state=").append(getStateString());
280: if (executionContext != null
281: && executionContext.getXid() != null) {
282: buffer.append(" xid=").append(executionContext.getXid());
283: buffer.append(" txTimeout=").append(
284: executionContext.getTransactionTimeout());
285: }
286: buffer.append(" waitType=");
287: switch (waitType) {
288: case WAIT_NONE: {
289: buffer.append("WAIT_NONE");
290: break;
291: }
292: case WAIT_FOR_START: {
293: buffer.append("WAIT_FOR_START");
294: break;
295: }
296: case WAIT_FOR_COMPLETE: {
297: buffer.append("WAIT_FOR_COMPLETE");
298: break;
299: }
300: default:
301: buffer.append("???");
302: }
303: if (startTimeout != WorkManager.INDEFINITE)
304: buffer.append(" startTimeout=").append(startTimeout);
305: long completionTimeout = getCompletionTimeout();
306: if (completionTimeout != -1)
307: buffer.append(" completionTimeout=").append(
308: completionTimeout);
309: if (blockedTime != 0)
310: buffer.append(" blockTime=").append(blockedTime);
311: buffer.append(" elapsedTime=").append(getElapsedTime());
312: if (workListener != null)
313: buffer.append(" workListener=").append(workListener);
314: if (exception != null)
315: buffer.append(" exception=").append(exception);
316: buffer.append("]");
317: return buffer.toString();
318: }
319: }
|