/* * JBoss, Home of Professional Open Source. * Copyright 2006, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.resource.work; import javax.resource.spi.work.ExecutionContext; import javax.resource.spi.work.Work; import javax.resource.spi.work.WorkCompletedException; import javax.resource.spi.work.WorkEvent; import javax.resource.spi.work.WorkException; import javax.resource.spi.work.WorkListener; import javax.resource.spi.work.WorkManager; import javax.resource.spi.work.WorkRejectedException; import org.jboss.logging.Logger; import org.jboss.util.JBossStringBuilder; import org.jboss.util.NestedRuntimeException; import org.jboss.util.threadpool.BasicTaskWrapper; import org.jboss.util.threadpool.StartTimeoutException; import org.jboss.util.threadpool.Task; /** * Wraps the resource adapter's work. * * @author <a href="mailto:adrian@jboss.org">Adrian Brock</a> * @version $Revision: 83419 $ */ public class WorkWrapper extends BasicTaskWrapper implements Task { /** The log */ private static final Logger log = Logger.getLogger(WorkWrapper.class); /** Whether we are tracing */ private boolean trace = log.isTraceEnabled(); /** The work */ private Work work; /** The execution context */ private ExecutionContext executionContext; /** the work listener */ private WorkListener workListener; /** The start timeout */ private long startTimeout; /** The work manager */ private JBossWorkManager workManager; /** The wait type */ private int waitType; /** The blocked time */ private long blockedTime; /** Any exception */ private WorkException exception; /** * Create a new WorkWrapper * * @param workManager the work manager * @param work the work * @param waitType the waitType * @param executionContext the execution context * @param workListener the WorkListener * @throws IllegalArgumentException for null work, execution context or a negative start timeout */ public WorkWrapper(JBossWorkManager workManager, Work work, int waitType, long startTimeout, ExecutionContext executionContext, WorkListener workListener) { super(); if (work == null) throw new IllegalArgumentException("Null work"); if (executionContext == null) throw new IllegalArgumentException("Null execution context"); if (startTimeout < 0) throw new IllegalArgumentException("Illegal start timeout: " + startTimeout); this.workManager = workManager; this.work = work; this.waitType = waitType; this.startTimeout = startTimeout; this.executionContext = executionContext; this.workListener = workListener; setTask(this); } /** * Get the work manager * * @return the work manager */ public JBossWorkManager getWorkManager() { return workManager; } /** * Retrieve the work * * @return the work */ public Work getWork() { return work; } /** * Retrieve the work listener * * @return the WorkListener */ public WorkListener getWorkListener() { return workListener; } /** * Retrieve the exection context * * @return the execution context */ public ExecutionContext getExecutionContext() { return executionContext; } /** * Retrieve the time blocked * * @return the blocked time */ public long getBlockedElapsed() { return blockedTime; } /** * Get any exception * * @return the exception or null if there is none */ public WorkException getWorkException() { return exception; } public int getWaitType() { return waitType; } public int getPriority() { return Thread.NORM_PRIORITY; } public long getStartTimeout() { return startTimeout; } public long getCompletionTimeout() { // [JBAS-6400] Conversion of seconds to milliseconds return executionContext.getTransactionTimeout() * 1000L; } public void execute() { if (trace) log.trace("Executing work " + this); try { workManager.startWork(this); } catch (WorkException e) { taskRejected(new NestedRuntimeException(e)); return; } try { work.run(); } finally { workManager.endWork(this); } if (trace) log.trace("Executed work " + this); } public void stop() { if (trace) log.trace("Stopping work " + this); work.release(); } public void accepted(long time) { blockedTime = time; if (trace) log.trace("Accepted work " + this); if (workListener != null) { WorkEvent event = new WorkEvent(workManager, WorkEvent.WORK_ACCEPTED, work, null); workListener.workAccepted(event); } } public void rejected(long time, Throwable throwable) { blockedTime = time; if (trace) { if (throwable != null) log.trace("Rejecting work " + this, throwable); else log.trace("Rejecting work " + this); } if (throwable != null) { exception = new WorkRejectedException(throwable); if (throwable instanceof StartTimeoutException) exception.setErrorCode(WorkRejectedException.START_TIMED_OUT); } workManager.cancelWork(this); if (workListener != null) { WorkEvent event = new WorkEvent(workManager, WorkEvent.WORK_ACCEPTED, work, exception); workListener.workRejected(event); } } public void started(long time) { if (waitType != WAIT_NONE) blockedTime = time; if (workListener != null) { WorkEvent event = new WorkEvent(workManager, WorkEvent.WORK_STARTED, work, null); workListener.workStarted(event); } } public void completed(long time, Throwable throwable) { if (waitType == WAIT_FOR_COMPLETE) blockedTime = time; if (throwable != null) exception = new WorkCompletedException(throwable); if (trace) log.trace("Completed work " + this); if (workListener != null) { WorkEvent event = new WorkEvent(workManager, WorkEvent.WORK_COMPLETED, work, exception); workListener.workCompleted(event); } } public String toString() { JBossStringBuilder buffer = new JBossStringBuilder(100); buffer.append("WorkWrapper@").append(Integer.toHexString(System.identityHashCode(this))); buffer.append("[workManger=").append(workManager); buffer.append(" work=").append(work); buffer.append(" state=").append(getStateString()); if (executionContext != null && executionContext.getXid() != null) { buffer.append(" xid=").append(executionContext.getXid()); buffer.append(" txTimeout=").append(executionContext.getTransactionTimeout()); } buffer.append(" waitType="); switch (waitType) { case WAIT_NONE: { buffer.append("WAIT_NONE"); break; } case WAIT_FOR_START: { buffer.append("WAIT_FOR_START"); break; } case WAIT_FOR_COMPLETE: { buffer.append("WAIT_FOR_COMPLETE"); break; } default: buffer.append("???"); } if (startTimeout != WorkManager.INDEFINITE) buffer.append(" startTimeout=").append(startTimeout); long completionTimeout = getCompletionTimeout(); if (completionTimeout != -1) buffer.append(" completionTimeout=").append(completionTimeout); if (blockedTime != 0) buffer.append(" blockTime=").append(blockedTime); buffer.append(" elapsedTime=").append(getElapsedTime()); if (workListener != null) buffer.append(" workListener=").append(workListener); if (exception != null) buffer.append(" exception=").append(exception); buffer.append("]"); return buffer.toString(); } }