You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by ch...@apache.org on 2003/11/16 23:42:20 UTC

cvs commit: incubator-geronimo/modules/core/src/test/org/apache/geronimo/connector/work PooledWorkManagerTest.java

chirino     2003/11/16 14:42:20

  Added:       modules/core/src/deploy workmanager-service.xml
               modules/core/src/java/org/apache/geronimo/connector/work
                        GeronimoWorkManager.java WorkManagerUtil.java
                        WorkerContext.java
               modules/core/src/java/org/apache/geronimo/connector/work/pool
                        AbstractWorkExecutorPool.java
                        ScheduleWorkExecutorPool.java
                        StartWorkExecutorPool.java
                        SyncWorkExecutorPool.java
                        TimedOutPooledExecutor.java WorkExecutorPool.java
               modules/core/src/test/org/apache/geronimo/connector/work
                        PooledWorkManagerTest.java
  Log:
  PR: GERONIMO-73
  Submitted by: Gianny DAMOUR
  
  This is the submited patch converted over to use GeronimoMBean for lifecycle managment and placed under the o.a.g.connector.work package.
  
  Revision  Changes    Path
  1.1                  incubator-geronimo/modules/core/src/deploy/workmanager-service.xml
  
  Index: workmanager-service.xml
  ===================================================================
  <?xml version="1.0" encoding="UTF-8"?>
  <components>
      <class-space name="geronimo.system:role=ClassSpace,name=System"/>
  
      <!-- ============================================================ -->
      <!-- Starts the Work Manager                                      -->
      <!-- ============================================================ -->
      <mbean descriptor="org.apache.geronimo.connector.work.GeronimoWorkManager"
      	name="geronimo.jca:role=WorkManager">
      </mbean>
      
      <!-- ============================================================ -->
      <!-- Starts the Work Executor Pool in charge of the treatment of  -->
      <!-- synchronous works                                            -->
      <!-- ============================================================ -->
      <mbean descriptor="org.apache.geronimo.connector.work.pool.SyncWorkExecutorPool"
      	name="geronimo.jca:role=SynchWorkExecutorPool">
          <constructor>
              <arg type="int">1</arg>
              <arg type="int">1</arg>
          </constructor>
      </mbean>
  
      <!-- ============================================================ -->
      <!-- Starts the Work Executor Pool in charge of the treatment of  -->
      <!-- synchronous works until the work start.                      -->
      <!-- ============================================================ -->
      <mbean descriptor="org.apache.geronimo.connector.work.pool.StartWorkExecutorPool"
      	name="geronimo.jca:role=StartWorkExecutorPool">
          <constructor>
              <arg type="int">1</arg>
              <arg type="int">1</arg>
          </constructor>
      </mbean>
  
      <!-- ============================================================ -->
      <!-- Starts the Work Executor Pool in charge of the treatment of  -->
      <!-- asynchronous works.                                          -->
      <!-- ============================================================ -->
      <mbean descriptor="org.apache.geronimo.connector.work.pool.ScheduleWorkExecutorPool"
      	name="geronimo.jca:role=ScheduleWorkExecutorPool">
          <constructor>
              <arg type="int">1</arg>
              <arg type="int">1</arg>
          </constructor>
      </mbean>
  
  </components>
  
  
  
  1.1                  incubator-geronimo/modules/core/src/java/org/apache/geronimo/connector/work/GeronimoWorkManager.java
  
  Index: GeronimoWorkManager.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Geronimo", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * ====================================================================
   */
  
  package org.apache.geronimo.connector.work;
  import javax.management.MBeanOperationInfo;
  import javax.resource.spi.work.ExecutionContext;
  import javax.resource.spi.work.Work;
  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.apache.geronimo.kernel.management.State;
  import org.apache.geronimo.kernel.service.GeronimoMBeanContext;
  import org.apache.geronimo.kernel.service.GeronimoMBeanInfo;
  import org.apache.geronimo.kernel.service.GeronimoMBeanTarget;
  import org.apache.geronimo.kernel.service.GeronimoOperationInfo;
  import org.apache.geronimo.kernel.service.GeronimoParameterInfo;
  import org.apache.geronimo.connector.work.pool.WorkExecutorPool;
  
  /**
   * WorkManager implementation which uses under the cover three WorkExecutorPool
   * - one for each synchronization policy - in order to dispatch the submitted 
   * Work instances. 
   * 
   * @version $Revision: 1.1 $ $Date: 2003/11/16 22:42:20 $
   */
  public class GeronimoWorkManager implements WorkManager, GeronimoMBeanTarget {
  
      /**
       * Pool of threads used by this WorkManager in order to process
       * synchronously the submitted Work instances 
       */
      private WorkExecutorPool m_syncWorkExecutorPool;
  
      /**
       * Pool of threads used by this WorkManager in order to process
       * the Work instances submitted via the startWork methods. 
       */
      private WorkExecutorPool m_startWorkExecutorPool;
  
      /**
       * Pool of threads used by this WorkManager in order to process
       * scheduled Work instances 
       */
      private WorkExecutorPool m_scheduledWorkExecutorPool;
  
      private GeronimoMBeanContext geronimoMBeanContext;
  
      /**
       * Create a WorkManager. 
       */
      public GeronimoWorkManager() {
      }
  
      /**
       * Provides the GeronimoMBean description for this class
       * @return
       */
      public static GeronimoMBeanInfo getGeronimoMBeanInfo() throws Exception {
  
          // TODO: add descriptions to all operations.
          GeronimoMBeanInfo rc = new GeronimoMBeanInfo();
          rc.setTargetClass(GeronimoWorkManager.class);
          rc.addOperationInfo(
              new GeronimoOperationInfo(
                  "setSyncExecutor",
                  new GeronimoParameterInfo[] { new GeronimoParameterInfo("pool", WorkExecutorPool.class, "")},
                  MBeanOperationInfo.ACTION,
                  ""));
          rc.addOperationInfo(
              new GeronimoOperationInfo(
                  "setStartExecutor",
                  new GeronimoParameterInfo[] { new GeronimoParameterInfo("pool", WorkExecutorPool.class, "")},
                  MBeanOperationInfo.ACTION,
                  ""));
          rc.addOperationInfo(
              new GeronimoOperationInfo(
                  "setAsyncExecutor",
                  new GeronimoParameterInfo[] { new GeronimoParameterInfo("pool", WorkExecutorPool.class, "")},
                  MBeanOperationInfo.ACTION,
                  ""));
          return rc;
  
      }
  
      /**
       * Set the executor in charge of the processing of synchronous works.
       * @param anExecutorPool An executor.
       */
      public void setSyncExecutor(WorkExecutorPool anExecutorPool) {
          m_syncWorkExecutorPool = anExecutorPool;
      }
  
      /**
       * Set the executor in charge of the processing of synchronous until start
       * works.
       * @param anExecutorPool An executor.
       */
      public void setStartExecutor(WorkExecutorPool anExecutorPool) {
          m_startWorkExecutorPool = anExecutorPool;
      }
  
      /**
       * Set the executor in charge of the processing of asynchronous works.
       * @param anExecutorPool An executor.
       */
      public void setAsyncExecutor(WorkExecutorPool anExecutorPool) {
          m_scheduledWorkExecutorPool = anExecutorPool;
      }
  
      /* (non-Javadoc)
       * @see javax.resource.spi.work.WorkManager#doWork(javax.resource.spi.work.Work)
       */
      public void doWork(Work work) throws WorkException {
          checkStateBeforeAccept(m_syncWorkExecutorPool, "synchronous");
          m_syncWorkExecutorPool.executeWork(new WorkerContext(work));
      }
  
      /* (non-Javadoc)
       * @see javax.resource.spi.work.WorkManager#doWork(javax.resource.spi.work.Work, long, javax.resource.spi.work.ExecutionContext, javax.resource.spi.work.WorkListener)
       */
      public void doWork(Work work, long startTimeout, ExecutionContext execContext, WorkListener workListener) throws WorkException {
          checkStateBeforeAccept(m_syncWorkExecutorPool, "synchronous");
          WorkerContext workWrapper = new WorkerContext(work, startTimeout, execContext, workListener);
          workWrapper.setThreadPriority(Thread.currentThread().getPriority());
          m_syncWorkExecutorPool.executeWork(workWrapper);
      }
  
      /* (non-Javadoc)
       * @see javax.resource.spi.work.WorkManager#startWork(javax.resource.spi.work.Work)
       */
      public long startWork(Work work) throws WorkException {
          checkStateBeforeAccept(m_startWorkExecutorPool, "synchronous until start");
          WorkerContext workWrapper = new WorkerContext(work);
          workWrapper.setThreadPriority(Thread.currentThread().getPriority());
          m_startWorkExecutorPool.executeWork(workWrapper);
          return System.currentTimeMillis() - workWrapper.getAcceptedTime();
      }
  
      /* (non-Javadoc)
       * @see javax.resource.spi.work.WorkManager#startWork(javax.resource.spi.work.Work, long, javax.resource.spi.work.ExecutionContext, javax.resource.spi.work.WorkListener)
       */
      public long startWork(Work work, long startTimeout, ExecutionContext execContext, WorkListener workListener) throws WorkException {
          checkStateBeforeAccept(m_startWorkExecutorPool, "synchronous until start");
          WorkerContext workWrapper = new WorkerContext(work, startTimeout, execContext, workListener);
          workWrapper.setThreadPriority(Thread.currentThread().getPriority());
          m_startWorkExecutorPool.executeWork(workWrapper);
          return System.currentTimeMillis() - workWrapper.getAcceptedTime();
      }
  
      /* (non-Javadoc)
       * @see javax.resource.spi.work.WorkManager#scheduleWork(javax.resource.spi.work.Work)
       */
      public void scheduleWork(Work work) throws WorkException {
          checkStateBeforeAccept(m_scheduledWorkExecutorPool, "asynchronous");
          WorkerContext workWrapper = new WorkerContext(work);
          workWrapper.setThreadPriority(Thread.currentThread().getPriority());
          m_scheduledWorkExecutorPool.executeWork(workWrapper);
      }
  
      /* (non-Javadoc)
       * @see javax.resource.spi.work.WorkManager#scheduleWork(javax.resource.spi.work.Work, long, javax.resource.spi.work.ExecutionContext, javax.resource.spi.work.WorkListener)
       */
      public void scheduleWork(Work work, long startTimeout, ExecutionContext execContext, WorkListener workListener) throws WorkException {
          checkStateBeforeAccept(m_scheduledWorkExecutorPool, "asynchronous");
          WorkerContext workWrapper = new WorkerContext(work, startTimeout, execContext, workListener);
          workWrapper.setThreadPriority(Thread.currentThread().getPriority());
          m_scheduledWorkExecutorPool.executeWork(workWrapper);
      }
  
      /**
       * This method MUST be called prior to accept a Work instance. It ensures
       * that the state of this WorkManager is running.
       * 
       * @throws WorkRejectedException Indicates that this WorkManager is not
       * running and hence that a work can not be accepted.
       */
      private void checkStateBeforeAccept(WorkExecutorPool aPool, String aType) throws WorkRejectedException {
          try {
              if (!(geronimoMBeanContext.getState() == State.RUNNING_INDEX)) {
                  throw new WorkRejectedException("WorkManager is not running.", WorkException.INTERNAL);
              } else if (null == aPool) {
                  throw new WorkRejectedException(
                      "WorkManager is not partially" + " running. Its " + aType + " work facilities are unmounted.",
                      WorkException.INTERNAL);
              }
          } catch (Exception e) {
              throw new WorkRejectedException("WorkManager is not ready.", WorkException.INTERNAL);
          }
      }
      
      /**
       * @see org.apache.geronimo.kernel.service.GeronimoMBeanTarget#setMBeanContext(org.apache.geronimo.kernel.service.GeronimoMBeanContext)
       */
      public void setMBeanContext(GeronimoMBeanContext geronimoMBeanContext) {
          this.geronimoMBeanContext = geronimoMBeanContext;
      }
  
      /**
       * @see org.apache.geronimo.kernel.service.GeronimoMBeanTarget#canStart()
       */
      public boolean canStart() {
          return true;
      }
  
      /**
       * @see org.apache.geronimo.kernel.service.GeronimoMBeanTarget#doStart()
       */
      public void doStart() {
      }
  
      /**
       * @see org.apache.geronimo.kernel.service.GeronimoMBeanTarget#canStop()
       */
      public boolean canStop() {
          return true;
      }
  
      /**
       * @see org.apache.geronimo.kernel.service.GeronimoMBeanTarget#doStop()
       */
      public void doStop() {
      }
  
      /**
       * @see org.apache.geronimo.kernel.service.GeronimoMBeanTarget#doFail()
       */
      public void doFail() {
      }
  
  }
  
  
  
  1.1                  incubator-geronimo/modules/core/src/java/org/apache/geronimo/connector/work/WorkManagerUtil.java
  
  Index: WorkManagerUtil.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Geronimo", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * ====================================================================
   */
  
  package org.apache.geronimo.connector.work;
  
  import javax.management.MBeanServer;
  import javax.management.ObjectName;
  
  import org.apache.geronimo.kernel.jmx.JMXUtil;
  import org.apache.geronimo.kernel.jmx.MBeanProxyFactory;
  
  /**
   * WorkManager helper.
   *  
   * @version $Revision: 1.1 $ $Date: 2003/11/16 22:42:20 $
   */
  public class WorkManagerUtil
  {
      
      /**
       * Name of the WorkManager.
       */
      public static final ObjectName WORK_MANAGER_NAME =
          JMXUtil.getObjectName("geronimo.jca:role=WorkManager");
          
      /**
       * Name of the synchronous work executor.
       */
      public static final ObjectName SYNC_EXECUTOR_NAME =
          JMXUtil.getObjectName("geronimo.jca:role=SynchWorkExecutorPool");
  
      /**
       * Name of the synchronous until start work executor.
       */
      public static final ObjectName START_EXECUTOR_NAME =
          JMXUtil.getObjectName("geronimo.jca:role=StartWorkExecutorPool");
  
      /**
       * Name of the asynchronous work executor.
       */
      public static final ObjectName ASYNC_EXECUTOR_NAME =
          JMXUtil.getObjectName("geronimo.jca:role=ScheduleWorkExecutorPool");
              
  }
  
  
  
  1.1                  incubator-geronimo/modules/core/src/java/org/apache/geronimo/connector/work/WorkerContext.java
  
  Index: WorkerContext.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Geronimo", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * ====================================================================
   */
  
  package org.apache.geronimo.connector.work;
  
  import javax.resource.spi.work.ExecutionContext;
  import javax.resource.spi.work.Work;
  import javax.resource.spi.work.WorkAdapter;
  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.WorkRejectedException;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  
  import EDU.oswego.cs.dl.util.concurrent.Latch;
  
  /**
   * Work wrapper providing an execution context to a Work instance.
   * 
   * @version $Revision: 1.1 $ $Date: 2003/11/16 22:42:20 $
   */
  public class WorkerContext implements Work
  {
  
      private Log m_log = LogFactory.getLog(WorkerContext.class);
  
      /**
       * Null WorkListener used as the default WorkListener. 
       */    
      private static final WorkListener NULL_WORK_LISTENER = new WorkAdapter();
  
      /**
       * Priority of the thread which will execute this work.
       */
      private int m_threadPriority;
  
      /**
       * Actual work to be executed.
       */        
      private Work m_adaptee;
  
      /**
       * Indicates if this work has been accepted.
       */
      private boolean m_isAccepted;
  
      /**
       * System.currentTimeMillis() when the Work has been accepted.
       */
      private long m_acceptedTime;
  
      /**
       * Number of times that the execution of this work has been tried.
       */
      private int m_nbRetry;
  
      /**
       * time duration (in milliseconds) within which the execution of the Work 
       * instance must start.
       */
      private long m_startTimeOut;
      
      /**
       * execution context of the actual work to be executed.
       */
      private ExecutionContext m_executionContext;
      
      /**
       * Listener to be notified during the life-cycle of the work treatment. 
       */
      private WorkListener m_workListener = NULL_WORK_LISTENER;
      
      /**
       * Work exception if any.
       */
      private WorkException m_workException;
  
      /**
       * A latch which is released when the work is started.
       */
      private Latch m_startLatch = new Latch();
      
      /**
       * A latch which is released when the work is completed.
       */
      private Latch m_endLatch = new Latch();
  
      /**
       * Create a WorkWrapper.
       * 
       * @param aWork Work wrapped by this instance.
       */        
      public WorkerContext(Work aWork) {
          m_adaptee = aWork;
      }
          
      /**
       * Create a WorkWrapper with the specified execution context.
       * 
       * @param aWork Work wrapped by this instance.
       * @param aStartTimeout a time duration (in milliseconds) within which the 
       * execution of the Work instance must start. 
       * @param execContext an object containing the execution context with which
       * the submitted Work instance must be executed.
       * @param workListener an object which would be notified when the various 
       * Work processing events (work accepted, work rejected, work started, 
       * work completed) occur.
       */        
      public WorkerContext(Work aWork, long aStartTimeout,
          ExecutionContext execContext,
          WorkListener workListener) {
          m_adaptee = aWork;
          m_startTimeOut = aStartTimeout;
          m_executionContext = execContext;
          if ( null != workListener ) {
              m_workListener = workListener;     
          }
      }
  
      /* (non-Javadoc)
       * @see javax.resource.spi.work.Work#release()
       */
      public void release() {
          m_adaptee.release();            
      }
  
      /**
       * Defines the thread priority level of the thread which will be dispatched
       * to process this work. This priority level must be the same one for a
       * given resource adapter. 
       */
      public void setThreadPriority(int aPriority) {
          m_threadPriority = aPriority;
      }
  
      /**
       * Gets the thread priority level of the thread which will be dispatched
       * to process this work. This priority level must be the same one for a
       * given resource adapter. 
       */
      public int getThreadPriority() {
          return m_threadPriority;
      }
  
      /**
       * Used by a Work executor in order to notify this work that it has been
       * accepted.
       * 
       * @param anObject Object on which the event initially occurred. It should
       * be the work executor.
       */
      public synchronized void workAccepted(Object anObject) {
          m_isAccepted = true;
          m_acceptedTime = System.currentTimeMillis();
          m_workListener.workAccepted(new WorkEvent(anObject,
              WorkEvent.WORK_ACCEPTED, m_adaptee, null));
      }
  
      /**
       * System.currentTimeMillis() when the Work has been accepted.
       *
       * @return when the work has ben accepted.
       */
      public synchronized long getAcceptedTime() {
          return m_acceptedTime;
      }
  
      /**
       * Gets the time duration (in milliseconds) within which the execution of 
       * the Work instance must start.
       * 
       * @return time out duration.
       */
      public long getStartTimeout() {
          return m_startTimeOut;
      }
  
      /**
       * Used by a Work executor in order to know if this work, which should be
       * accepted but not started has timed out. This method MUST be called prior
       * to retry the execution of a Work.
       * 
       * @return true if the work has timed out and false otherwise.
       */
      public synchronized boolean isTimedOut() {
          assert !m_isAccepted: "The work is not accepted.";
          // A value of 0 means that the work never times out.
          if ( 0 == m_startTimeOut ) {
             return false;
          }
          boolean isTimeout =
              System.currentTimeMillis() > m_acceptedTime + m_startTimeOut;
          if ( m_log.isDebugEnabled() ) {
              m_log.debug(this + " accepted at " + m_acceptedTime + 
              (isTimeout? " has timed out.":" has not timed out. ") +
              m_nbRetry + " retries have been performed.");        
          }
          if ( isTimeout ) {
              m_workException = new WorkRejectedException("Time out.",
                  WorkException.START_TIMED_OUT);
              m_workListener.workRejected(
                  new WorkEvent(this, WorkEvent.WORK_REJECTED, m_adaptee,
                  m_workException));
              return true; 
          }
          m_nbRetry++;
          return isTimeout;
      }
  
      /**
       * Gets the WorkException, if any, thrown during this work execution.
       * 
       * @return WorkException, if any.
       */
      public synchronized WorkException getWorkException() {
          return m_workException;
      }
  
      /* (non-Javadoc)
       * @see java.lang.Runnable#run()
       */
      public void run() {
          if ( isTimedOut() ) {
              // In case of a time out, one releases the start and end latches
              // to prevent a dead-lock.
              m_startLatch.release();
              m_endLatch.release();
              return;
          }
          // Implementation note: the work listener is notified prior to release
          // the start lock. This behavior is intentional and seems to be the
          // more conservative.
          m_workListener.workStarted(
              new WorkEvent(this, WorkEvent.WORK_STARTED, m_adaptee, null));
          m_startLatch.release();
          try {
              m_adaptee.run();
              m_workListener.workCompleted(
                  new WorkEvent(this, WorkEvent.WORK_COMPLETED, m_adaptee, null));
          } catch (Throwable e) {
              m_workException = new WorkCompletedException(e);
              m_workListener.workRejected(
                  new WorkEvent(this, WorkEvent.WORK_REJECTED, m_adaptee,
                  m_workException));
          } finally  {
              m_endLatch.release();
          }
      }
  
      /**
       * Provides a latch, which can be used to wait the start of a work 
       * execution.
       * 
       * @return Latch that a caller can acquire to wait for the start of a 
       * work execution.
       */
      public synchronized Latch provideStartLatch() {
          return m_startLatch;
      }
  
      /**
       * Provides a latch, which can be used to wait the end of a work 
       * execution.
       * 
       * @return Latch that a caller can acquire to wait for the end of a 
       * work execution.
       */
      public synchronized Latch provideEndLatch() {
          return m_endLatch;
      }
  
      public String toString() {
          return "Work :" + m_adaptee;  
      }
      
  }
  
  
  
  1.1                  incubator-geronimo/modules/core/src/java/org/apache/geronimo/connector/work/pool/AbstractWorkExecutorPool.java
  
  Index: AbstractWorkExecutorPool.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Geronimo", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * ====================================================================
   */
  
  package org.apache.geronimo.connector.work.pool;
  
  import javax.resource.spi.work.WorkCompletedException;
  import javax.resource.spi.work.WorkException;
  
  import org.apache.geronimo.kernel.service.GeronimoAttributeInfo;
  import org.apache.geronimo.kernel.service.GeronimoMBeanInfo;
  import org.apache.geronimo.connector.work.WorkerContext;
  
  import EDU.oswego.cs.dl.util.concurrent.Channel;
  
  /**
   * Based class for WorkExecutorPool. A sub-class defines the synchronization
   * policy (should the call block until the end of the work; or when it starts
   * et cetera).
   *
   * @jmx:mbean
   *      extends="org.apache.geronimo.kernel.management.StateManageable,org.apache.geronimo.kernel.management.ManagedObject"
   *   
   * @version $Revision: 1.1 $ $Date: 2003/11/16 22:42:20 $
   */
  public abstract class AbstractWorkExecutorPool implements WorkExecutorPool {
  
      /**
       * A timed out pooled executor.
       */
      private TimedOutPooledExecutor m_pooledExecutor;
  
      /**
       * Creates a pool with the specified minimum and maximum sizes.
       * 
       * @param aMinSize Minimum size of the work executor pool.
       * @param aMaxSize Maximum size of the work executor pool.
       * @param aRetryDuration Duration (in milliseconds) to wait prior to retry 
       * the execution of a Work.
       */
      public AbstractWorkExecutorPool(int aMinSize, int aMaxSize) {
          m_pooledExecutor = new TimedOutPooledExecutor();
          m_pooledExecutor.setMinimumPoolSize(aMinSize);
          m_pooledExecutor.setMaximumPoolSize(aMaxSize);
          m_pooledExecutor.waitWhenBlocked();
      }
  
      /**
       * Creates a pool with the specified minimum and maximum sizes.
       * 
       * @param Queue to be used on top of the pool.
       * @param aMinSize Minimum size of the work executor pool.
       * @param aMaxSize Maximum size of the work executor pool.
       * @param aRetryDuration Duration (in milliseconds) to wait prior to retry 
       * the execution of a Work.
       */
      public AbstractWorkExecutorPool(Channel aChannel, int aMinSize, int aMaxSize) {
          m_pooledExecutor = new TimedOutPooledExecutor(aChannel);
          m_pooledExecutor.setMinimumPoolSize(aMinSize);
          m_pooledExecutor.setMaximumPoolSize(aMaxSize);
          m_pooledExecutor.waitWhenBlocked();
      }
  
      /**
       * Delegates the work execution to the pooled executor.
       * 
       * @see EDU.oswego.cs.dl.util.concurrent.PooledExecutor#execute(java.lang.Runnable)
       */
      protected void execute(WorkerContext aWork) throws InterruptedException {
          m_pooledExecutor.execute(aWork);
      }
  
      /**
       * @see org.apache.geronimo.workmanagement.WorkExecutorPool#execute(org.apache.geronimo.workmanagement.WorkWrapper)
       */
      public void executeWork(WorkerContext aWork) throws WorkException {
          aWork.workAccepted(this);
          try {
              doExecute(aWork);
              WorkException exception = aWork.getWorkException();
              if (null != exception) {
                  throw exception;
              }
          } catch (InterruptedException e) {
              WorkCompletedException wcj = new WorkCompletedException("The execution has been interrupted.", e);
              wcj.setErrorCode(WorkException.INTERNAL);
              throw wcj;
          }
      }
  
      public static GeronimoMBeanInfo getGeronimoMBeanInfo() throws Exception {
          GeronimoMBeanInfo rc = new GeronimoMBeanInfo();
          rc.setTargetClass(AbstractWorkExecutorPool.class);
          rc.addAttributeInfo(new GeronimoAttributeInfo("PoolSize", true, false));
          rc.addAttributeInfo(new GeronimoAttributeInfo("MinimumPoolSize", true, true));
          rc.addAttributeInfo(new GeronimoAttributeInfo("MaximumPoolSize", true, true));
          return rc;
      }
  
      /**
       * @see org.apache.geronimo.work.WorkExecutorPool#getPoolSize()
       */
      public int getPoolSize() {
          return m_pooledExecutor.getPoolSize();
      }
  
      /**
       * @see org.apache.geronimo.work.WorkExecutorPool#getMinimumPoolSize()
       */
      public int getMinimumPoolSize() {
          return m_pooledExecutor.getMinimumPoolSize();
      }
  
      /**
       * @see org.apache.geronimo.work.WorkExecutorPool#setMinimumPoolSize(int)
       */
      public void setMinimumPoolSize(int aSize) {
          m_pooledExecutor.setMinimumPoolSize(aSize);
      }
  
      /**
       * @see org.apache.geronimo.work.WorkExecutorPool#getMaximumPoolSize()
       */
      public int getMaximumPoolSize() {
          return m_pooledExecutor.getMaximumPoolSize();
      }
  
      /**
       * @see org.apache.geronimo.work.WorkExecutorPool#setMaximumPoolSize(int)
       */
      public void setMaximumPoolSize(int aSize) {
          m_pooledExecutor.setMaximumPoolSize(aSize);
      }
  
      /**
       * This method must be implemented by sub-classes in order to provide a
       * synchronization policy.
       * 
       * @param aWork Work to be executed.
       * 
       * @throws WorkException Indicates the work has failed.
       * @throws InterruptedException Indicates that the thread in charge of the 
       * execution of the specified work dies. 
       */
      protected abstract void doExecute(WorkerContext aWork) throws WorkException, InterruptedException;
  
      /* (non-Javadoc)
       * @see org.apache.geronimo.connector.WorkExecutorPool#stop()
       */
      public void doStop() {
          m_pooledExecutor.shutdownAfterProcessingCurrentlyQueuedTasks();
      }
  
  }
  
  
  
  1.1                  incubator-geronimo/modules/core/src/java/org/apache/geronimo/connector/work/pool/ScheduleWorkExecutorPool.java
  
  Index: ScheduleWorkExecutorPool.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Geronimo", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * ====================================================================
   */
  
  package org.apache.geronimo.connector.work.pool;
  
  import javax.management.MalformedObjectNameException;
  import javax.management.ObjectName;
  import javax.resource.spi.work.WorkException;
  
  import org.apache.geronimo.kernel.service.GeronimoMBeanEndpoint;
  import org.apache.geronimo.kernel.service.GeronimoMBeanInfo;
  import org.apache.geronimo.connector.work.GeronimoWorkManager;
  import org.apache.geronimo.connector.work.WorkerContext;
  
  import EDU.oswego.cs.dl.util.concurrent.LinkedQueue;
  
  /**
   * WorkExecutorPool which treats the submitted Work instances asynchronously. 
   * More accurately, its execute method returns immediately after the work 
   * submission.
   *  
   * @jmx:mbean extends="AbstractWorkExecutorPoolMBean"
   * 
   * @version $Revision: 1.1 $ $Date: 2003/11/16 22:42:20 $
   */
  public class ScheduleWorkExecutorPool
      extends AbstractWorkExecutorPool
  {
  
      /**
       * Creates a pool with the specified minimum and maximum sizes.
       * 
       * @param aMinSize Minimum size of the work executor pool.
       * @param aMaxSize Maximum size of the work executor pool.
       */
      public ScheduleWorkExecutorPool(int aMinSize, int aMaxSize) {
          super(new LinkedQueue(), aMinSize, aMaxSize);
      }
  
      public void setGeronimoWorkManager( GeronimoWorkManager wm ) {
          wm.setAsyncExecutor(this);
      }
      
      /**
       */
      public void doExecute(WorkerContext aWork)
          throws WorkException, InterruptedException {
          super.execute(aWork);
      }
  
      
      public static GeronimoMBeanInfo getGeronimoMBeanInfo() throws Exception {
          try {
              GeronimoMBeanInfo rc =AbstractWorkExecutorPool.getGeronimoMBeanInfo();
              rc.setTargetClass(ScheduleWorkExecutorPool.class);
              rc.addEndpoint(new GeronimoMBeanEndpoint("GeronimoWorkManager", GeronimoWorkManager.class, new ObjectName("geronimo.jca:role=WorkManager"), true));
              return rc;
          } catch (MalformedObjectNameException e) {
              throw new RuntimeException("GeronimoMBeanInfo could not be gernerated.", e);
          }
      }
      
  }
  
  
  
  1.1                  incubator-geronimo/modules/core/src/java/org/apache/geronimo/connector/work/pool/StartWorkExecutorPool.java
  
  Index: StartWorkExecutorPool.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Geronimo", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * ====================================================================
   */
  
  package org.apache.geronimo.connector.work.pool;
  
  import javax.management.MalformedObjectNameException;
  import javax.management.ObjectName;
  import javax.resource.spi.work.WorkException;
  
  import org.apache.geronimo.kernel.service.GeronimoMBeanEndpoint;
  import org.apache.geronimo.kernel.service.GeronimoMBeanInfo;
  import org.apache.geronimo.connector.work.GeronimoWorkManager;
  import org.apache.geronimo.connector.work.WorkerContext;
  
  import EDU.oswego.cs.dl.util.concurrent.Latch;
  import EDU.oswego.cs.dl.util.concurrent.LinkedQueue;
  
  /**
   * WorkExecutorPool which treats the submitted Work instances synchronously 
   * until the work starts. More accurately, its execute method returns when the
   * work is started.
   * 
   * @jmx:mbean extends="AbstractWorkExecutorPoolMBean"
   *  
   * @version $Revision: 1.1 $ $Date: 2003/11/16 22:42:20 $
   */
  public class StartWorkExecutorPool
      extends AbstractWorkExecutorPool
  {
  
      /**
       * Creates a pool with the specified minimum and maximum sizes.
       * 
       * @param aMinSize Minimum size of the work executor pool.
       * @param aMaxSize Maximum size of the work executor pool.
       */
      public StartWorkExecutorPool(int aMinSize, int aMaxSize) {
          super(new LinkedQueue(), aMinSize, aMaxSize);
      }
      
      public void setGeronimoWorkManager( GeronimoWorkManager wm ) {
          wm.setStartExecutor(this);
      }
  
      /**
       * In the case of a synchronous execution, the Work has been executed and
       * one needs to retrieve the WorkException thrown during this execution, if
       * any.
       * 
       * @exception WorkException Not thrown.
       * @exception InterruptedException Indicates that this work execution
       * has been interrupted.
       */
      public void doExecute(WorkerContext aWork)
          throws WorkException, InterruptedException {
          Latch latch = aWork.provideStartLatch();
          super.execute(aWork);
          latch.acquire();
      }
  
      public static GeronimoMBeanInfo getGeronimoMBeanInfo() throws Exception {
          try {
              GeronimoMBeanInfo rc =AbstractWorkExecutorPool.getGeronimoMBeanInfo();
              rc.setTargetClass(StartWorkExecutorPool.class);
              rc.addEndpoint(new GeronimoMBeanEndpoint("GeronimoWorkManager", GeronimoWorkManager.class, new ObjectName("geronimo.jca:role=WorkManager"), true));
              return rc;
          } catch (MalformedObjectNameException e) {
              throw new RuntimeException("GeronimoMBeanInfo could not be gernerated.", e);
          }
      }
      
  }
  
  
  
  1.1                  incubator-geronimo/modules/core/src/java/org/apache/geronimo/connector/work/pool/SyncWorkExecutorPool.java
  
  Index: SyncWorkExecutorPool.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Geronimo", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * ====================================================================
   */
  
  package org.apache.geronimo.connector.work.pool;
  
  import javax.management.MalformedObjectNameException;
  import javax.management.ObjectName;
  import javax.resource.spi.work.WorkException;
  
  import org.apache.geronimo.kernel.service.GeronimoMBeanEndpoint;
  import org.apache.geronimo.kernel.service.GeronimoMBeanInfo;
  import org.apache.geronimo.connector.work.GeronimoWorkManager;
  import org.apache.geronimo.connector.work.WorkerContext;
  
  import EDU.oswego.cs.dl.util.concurrent.Latch;
  
  /**
   * WorkExecutorPool which treats the submitted Work instances synchronously. 
   * More accurately, its execute method blocks until the work is completed.
   *  
   * @version $Revision: 1.1 $ $Date: 2003/11/16 22:42:20 $
   */
  public class SyncWorkExecutorPool
      extends AbstractWorkExecutorPool
  {
  
      /**
       * Creates a pool with the specified minimum and maximum sizes.
       * 
       * @param aMinSize Minimum size of the work executor pool.
       * @param aMaxSize Maximum size of the work executor pool.
       */
      public SyncWorkExecutorPool(int aMinSize, int aMaxSize) {
          super(aMinSize, aMaxSize);
      }
          
      public void setGeronimoWorkManager( GeronimoWorkManager wm ) {
          wm.setSyncExecutor(this);
      }
  
      /**
       * In the case of a synchronous execution, the Work has been executed and
       * one needs to retrieve the WorkException thrown during this execution, if
       * any.
       * 
       * @exception WorkException Not thrown.
       * @exception InterruptedException Indicates that this work execution
       * has been interrupted.
       */
      public void doExecute(WorkerContext aWork)
          throws WorkException, InterruptedException {
          Latch latch = aWork.provideEndLatch();
          super.execute(aWork);
          latch.acquire();
      }
      
      public static GeronimoMBeanInfo getGeronimoMBeanInfo() throws Exception {
          try {
              GeronimoMBeanInfo rc =AbstractWorkExecutorPool.getGeronimoMBeanInfo();
              rc.setTargetClass(SyncWorkExecutorPool.class);
              rc.addEndpoint(new GeronimoMBeanEndpoint("GeronimoWorkManager", GeronimoWorkManager.class, new ObjectName("geronimo.jca:role=WorkManager"), true));
              return rc;
          } catch (MalformedObjectNameException e) {
              throw new RuntimeException("GeronimoMBeanInfo could not be gernerated.", e);
          }
      }
      
  }
  
  
  
  1.1                  incubator-geronimo/modules/core/src/java/org/apache/geronimo/connector/work/pool/TimedOutPooledExecutor.java
  
  Index: TimedOutPooledExecutor.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Geronimo", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * ====================================================================
   */
  
  package org.apache.geronimo.connector.work.pool;
  
  import org.apache.geronimo.connector.work.WorkerContext;
  
  import EDU.oswego.cs.dl.util.concurrent.Channel;
  import EDU.oswego.cs.dl.util.concurrent.PooledExecutor;
  
  /**
   * PooledExecutor enforcing a timed out "blocked execution policy". The works
   * submitted to this pooled executor MUST be a WorkWrapper.
   * 
   * @version $Revision: 1.1 $ $Date: 2003/11/16 22:42:20 $
   */
  public class TimedOutPooledExecutor extends PooledExecutor
  {
      
      public TimedOutPooledExecutor() {
          setBlockedExecutionHandler(new TimedOutSpinHandler());
      }
      
      public TimedOutPooledExecutor(Channel aChannel) {
          super(aChannel);
          setBlockedExecutionHandler(new TimedOutSpinHandler());
      }
  
      /**
       * Executes the provided task, which MUST be an instance of WorkWrapper.
       * 
       * @throws IllegalArgumentException Indicates that the provided task is not
       * a  WorkWrapper.
       */
      public void execute(Runnable aTask) throws InterruptedException {
          if ( aTask instanceof WorkerContext ) {
              super.execute(aTask);
              return;
          }
          throw new IllegalArgumentException("Please submit a WorkWrapper");
      }
      
      /**
       * This class implements a time out policy when a work is blocked: it offers
       * the task to the pool until the work has timed out.
       * 
       * @version $Revision: 1.1 $ $Date: 2003/11/16 22:42:20 $
       */
      private class TimedOutSpinHandler
          implements PooledExecutor.BlockedExecutionHandler {
  
          /* (non-Javadoc)
           * @see EDU.oswego.cs.dl.util.concurrent.PooledExecutor.BlockedExecutionHandler#blockedAction(java.lang.Runnable)
           */
          public boolean blockedAction(Runnable arg0) throws InterruptedException {
              WorkerContext work = (WorkerContext) arg0;
              if ( !handOff_.offer(arg0, work.getStartTimeout()) ) {
                  // double check.
                  if ( work.isTimedOut() ) {
                      return false;
                  }
                  return true;
              }
              return true;
          }
      }
  }
  
  
  
  1.1                  incubator-geronimo/modules/core/src/java/org/apache/geronimo/connector/work/pool/WorkExecutorPool.java
  
  Index: WorkExecutorPool.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Geronimo", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * ====================================================================
   */
  
  package org.apache.geronimo.connector.work.pool;
  
  import javax.resource.spi.work.WorkException;
  
  import org.apache.geronimo.connector.work.WorkerContext;
  
  /**
   * Defines the operations that a pool in charge of the execution of Work
   * instances must expose.
   *  
   * @version $Revision: 1.1 $ $Date: 2003/11/16 22:42:20 $
   */
  public interface WorkExecutorPool
  {
  
      /**
       * Executes the specified work. The execution policy (synchronous vs. 
       * asynchronous) is implementation specific. 
       * 
       * @param aWork Work to be executed.
       * 
       * @throws WorkException Indicates that the Work instance can not be 
       * executed or that its execution has thrown an exception.
       */
      public void executeWork(WorkerContext aWork)  throws WorkException;
      
      /**
       * Gets the current number of active threads in the pool.
       * 
       * @return Number of active threads in the pool.
       */
      public int getPoolSize();
      
      /**
       * Gets the minimum number of threads to simultaneously execute.
       * 
       * @return Minimum size.
       */
      public int getMinimumPoolSize();
       
      /**
       * Sets the minimum number of threads to simultaneously execute.
       * 
       * @param aSize Minimum size.
       */
      public void setMinimumPoolSize(int aSize);
      
      /**
       * Gets the maximum number of threads to simultaneously execute.
       * 
       * @return Maximim size.
       */
      public int getMaximumPoolSize();
       
      /**
       * Sets the maximum number of threads to simultaneously execute.
       * 
       * @param Maximum size.
       */
      public void setMaximumPoolSize(int aSize);
       
  }
  
  
  
  1.1                  incubator-geronimo/modules/core/src/test/org/apache/geronimo/connector/work/PooledWorkManagerTest.java
  
  Index: PooledWorkManagerTest.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Geronimo", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * ====================================================================
   */
  
  package org.apache.geronimo.connector.work;
  
  import java.lang.reflect.Constructor;
  
  import javax.resource.spi.work.ExecutionContext;
  import javax.resource.spi.work.Work;
  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 junit.framework.TestCase;
  
  import org.apache.geronimo.kernel.jmx.JMXKernel;
  import org.apache.geronimo.kernel.management.State;
  import org.apache.geronimo.kernel.service.GeronimoMBeanContext;
  import org.apache.geronimo.connector.work.pool.ScheduleWorkExecutorPool;
  import org.apache.geronimo.connector.work.pool.StartWorkExecutorPool;
  import org.apache.geronimo.connector.work.pool.SyncWorkExecutorPool;
  
  /**
   * Timing is crucial for this test case, which focuses on the synchronous
   * specificities of the doWork, startWork and scheduleWork.
   *  
   * @version $Revision: 1.1 $ $Date: 2003/11/16 22:42:20 $
   */
  public class PooledWorkManagerTest extends TestCase
  {
  
      private JMXKernel m_kernel;
      private GeronimoWorkManager m_workManager;
      private static final int m_nbMin = 1;
      private static final int m_nbMax = 1;
      private static final int m_timeout = 3000;
      private static final int m_tempo = 2000;
  
      public PooledWorkManagerTest() throws Exception {
          super("WorkManager");
          initMinimalisticServer();
          m_workManager = new GeronimoWorkManager();
  
          // We are mocking the GeronimoMBeanContext
          m_workManager.setMBeanContext(new GeronimoMBeanContext(null, null, null){
              public int getState() throws Exception {
                  return State.RUNNING_INDEX;
              }
          });
          
          SyncWorkExecutorPool syncWorkExecutorPool = new SyncWorkExecutorPool(1, 1);
          syncWorkExecutorPool.setGeronimoWorkManager(m_workManager);
          
          StartWorkExecutorPool startWorkExecutorPool = new StartWorkExecutorPool(1, 1);
          startWorkExecutorPool.setGeronimoWorkManager(m_workManager);
          
          ScheduleWorkExecutorPool scheduleWorkExecutorPool = new ScheduleWorkExecutorPool(1, 1);
          scheduleWorkExecutorPool.setGeronimoWorkManager(m_workManager);
      }
  
      public void initMinimalisticServer() throws Exception {
      }
  
      public void testDoWork() throws Exception {
          int nbThreads = 3;
          AbstractDummyWork threads[] = helperTest(DummyDoWork.class, nbThreads);
          int nbStopped = 0;
          int nbTimeout = 0;
          for (int i = 0; i < threads.length; i++) {
              if ( threads[i].m_listener.m_event.getType() ==
                  WorkEvent.WORK_COMPLETED ) {
                  nbStopped++;
              } else if ( threads[i].m_listener.m_event.getType() ==
                  WorkEvent.WORK_REJECTED ) {
                  assertTrue("Should be a time out exception.",
                      threads[i].m_listener.m_event.getException().
                      getErrorCode() == WorkException.START_TIMED_OUT);
                  nbTimeout++;
              } else {
                  assertTrue("Works should be either in the WORK_COMPLETED or " +
                      "WORK_REJECTED state", false);
              }
          }
          assertTrue("Wrong number of works in the WORK_COMPLETED state: " +
              "expected " + (nbThreads - 1 ) + "; retrieved " + nbStopped,
              (nbThreads - 1 ) == nbStopped);
          assertTrue("Wrong number of works in the START_TIMED_OUT state: " +
              "expected 1; retrieved " + nbTimeout, 1 == nbTimeout);
      }
      
      public void testStartWork() throws Exception {
          AbstractDummyWork threads[] = helperTest(DummyStartWork.class, 2);
          int nbStopped = 0;
          int nbStarted = 0;
          for (int i = 0; i < threads.length; i++) {
              if ( threads[i].m_listener.m_event.getType() ==
                  WorkEvent.WORK_COMPLETED ) {
                  nbStopped++;
              } else if ( threads[i].m_listener.m_event.getType() ==
                  WorkEvent.WORK_STARTED ) {
                  nbStarted++;
              } else {
                  assertTrue("Works should be either in the WORK_COMPLETED or " +
                      "WORK_STARTED state", false);
              }
          }
          assertTrue("At least one work should be in the WORK_COMPLETED state.",
              nbStopped == 1);
          assertTrue("At least one work should be in the WORK_STARTED state.",
              nbStarted == 1);
      }
  
      public void testScheduleWork() throws Exception {
          AbstractDummyWork threads[] = helperTest(DummyScheduleWork.class, 3);
          int nbAccepted = 0;
          int nbStarted = 0;
          for (int i = 0; i < threads.length; i++) {
              if ( threads[i].m_listener.m_event.getType() ==
                  WorkEvent.WORK_ACCEPTED ) {
                  nbAccepted++;
              } else if ( threads[i].m_listener.m_event.getType() ==
                  WorkEvent.WORK_STARTED ) {
                  nbStarted++;
              } else {
                  assertTrue("Works should be eithe in the WORK_ACCEPTED or" +
                      "  WORK_STARTED state.", false);
              }
          }
          assertTrue("At least one work should be in the WORK_ACCEPTED state.",
              nbAccepted > 0);
      }
      
      private AbstractDummyWork[] helperTest(Class aWork, int nbThreads)
          throws Exception {
          Constructor constructor = aWork.getConstructor(
              new Class[]{WorkManager.class, String.class}); 
          AbstractDummyWork rarThreads[] =
              new AbstractDummyWork[nbThreads];
          for (int i = 0; i < nbThreads; i++) {
              rarThreads[i] = (AbstractDummyWork) constructor.newInstance(
                  new Object[] {m_workManager, "Work" + i});
              rarThreads[i].start();
          }
          for (int i = 0; i < nbThreads; i++) {
              rarThreads[i].join();
          }
          return rarThreads;
      }
      
      private static abstract class AbstractDummyWork extends Thread {
          public DummyWorkListener m_listener;
          protected WorkManager m_workManager;
          protected String m_name;
          public AbstractDummyWork(WorkManager aWorkManager, String aName) {
              m_workManager = aWorkManager;
              m_listener = new DummyWorkListener();
              m_name = aName;
          }
          public void run() {
              try {
                  perform(new DummyWork(m_name), m_timeout, null, m_listener);                
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
          protected abstract void perform(Work work,
              long startTimeout,
              ExecutionContext execContext,
              WorkListener workListener) throws Exception;
      }
  
      private static class DummyDoWork extends AbstractDummyWork {
          public DummyDoWork(WorkManager aWorkManager, String aName) {
              super(aWorkManager, aName);
          }
          protected void perform(Work work,
              long startTimeout,
              ExecutionContext execContext,
              WorkListener workListener) throws Exception {
              m_workManager.doWork(work, startTimeout, execContext, workListener);
          }
      }
      
      private static class DummyStartWork extends AbstractDummyWork {
          public DummyStartWork(WorkManager aWorkManager, String aName) {
              super(aWorkManager, aName);
          }
          protected void perform(Work work,
              long startTimeout,
              ExecutionContext execContext,
              WorkListener workListener) throws Exception {
              m_workManager.startWork(work, startTimeout, execContext, workListener);
          }
      }
      
      private static class DummyScheduleWork extends AbstractDummyWork {
          public DummyScheduleWork(WorkManager aWorkManager, String aName) {
              super(aWorkManager, aName);
          }
          protected void perform(Work work,
              long startTimeout,
              ExecutionContext execContext,
              WorkListener workListener) throws Exception {
              m_workManager.scheduleWork(work, startTimeout, execContext, workListener);
          }
      }
      
      private static class DummyWork implements Work {
          private String m_name;
          public DummyWork(String aName) {m_name = aName;}
          public void release() {}
          public void run() {
              try {
                  Thread.sleep(m_tempo);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
          }
          public String toString() {return m_name;}
      }
      
      private static class DummyWorkListener implements WorkListener {
          public WorkEvent m_event;
          public void workAccepted(WorkEvent e) {m_event = e;}
          public void workRejected(WorkEvent e) {m_event = e;}
          public void workStarted(WorkEvent e) {m_event = e;}
          public void workCompleted(WorkEvent e) {m_event = e;}
      }
  }