Coverage Report - org.mule.work.MuleWorkManager
 
Classes in this File Line Coverage Branch Coverage Complexity
MuleWorkManager
0%
0/75
0%
0/28
2.067
 
 1  
 /*
 2  
  * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
 3  
  * The software in this package is published under the terms of the CPAL v1.0
 4  
  * license, a copy of which has been included with this distribution in the
 5  
  * LICENSE.txt file.
 6  
  */
 7  
 package org.mule.work;
 8  
 
 9  
 import org.mule.api.MuleContext;
 10  
 import org.mule.api.MuleException;
 11  
 import org.mule.api.config.MuleConfiguration;
 12  
 import org.mule.api.config.ThreadingProfile;
 13  
 import org.mule.api.context.MuleContextAware;
 14  
 import org.mule.api.context.WorkManager;
 15  
 import org.mule.api.work.WorkExecutor;
 16  
 
 17  
 import java.text.MessageFormat;
 18  
 import java.util.List;
 19  
 
 20  
 import javax.resource.spi.XATerminator;
 21  
 import javax.resource.spi.work.ExecutionContext;
 22  
 import javax.resource.spi.work.Work;
 23  
 import javax.resource.spi.work.WorkCompletedException;
 24  
 import javax.resource.spi.work.WorkException;
 25  
 import javax.resource.spi.work.WorkListener;
 26  
 
 27  
 import edu.emory.mathcs.backport.java.util.concurrent.Executor;
 28  
 import edu.emory.mathcs.backport.java.util.concurrent.ExecutorService;
 29  
 import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
 30  
 
 31  
 import org.apache.commons.logging.Log;
 32  
 import org.apache.commons.logging.LogFactory;
 33  
 
 34  
 /**
 35  
  * <code>MuleWorkManager</code> is a JCA Work manager implementation used to manage
 36  
  * thread allocation for Mule components and connectors. This code has been adapted
 37  
  * from the Geronimo implementation.
 38  
  */
 39  
 public class MuleWorkManager implements WorkManager, MuleContextAware
 40  
 {
 41  
     /**
 42  
      * logger used by this class
 43  
      */
 44  0
     protected static final Log logger = LogFactory.getLog(MuleWorkManager.class);
 45  
 
 46  
     /**
 47  
      * Forced shutdown delay. The time the workManager will wait while threads are being
 48  
      * interrupted. The graceful shutdown timeout which is the amount of time that
 49  
      * the workManager will wait while the workManager completed pending and
 50  
      * currently executing jobs is configured using {@link MuleConfiguration}.
 51  
      */
 52  
     private static final long FORCEFUL_SHUTDOWN_TIMEOUT = 5000L;
 53  
 
 54  
     /**
 55  
      * The ThreadingProfile used for creation of the underlying ExecutorService
 56  
      */
 57  
     private final ThreadingProfile threadingProfile;
 58  
 
 59  
     /**
 60  
      * The actual pool of threads used by this MuleWorkManager to process the Work
 61  
      * instances submitted via the (do,start,schedule)Work methods.
 62  
      */
 63  
     private volatile ExecutorService workExecutorService;
 64  
     private final String name;
 65  
     private int gracefulShutdownTimeout;
 66  
     private MuleContext muleContext;
 67  
     
 68  
     /**
 69  
      * Various policies used for work execution
 70  
      */
 71  0
     private final WorkExecutor scheduleWorkExecutor = new ScheduleWorkExecutor();
 72  0
     private final WorkExecutor startWorkExecutor = new StartWorkExecutor();
 73  0
     private final WorkExecutor syncWorkExecutor = new SyncWorkExecutor();
 74  
 
 75  
     public MuleWorkManager(ThreadingProfile profile, String name, int shutdownTimeout)
 76  
     {
 77  0
         super();
 78  
 
 79  0
         if (name == null)
 80  
         {
 81  0
             name = "WorkManager#" + hashCode();
 82  
         }
 83  
 
 84  0
         this.threadingProfile = profile;
 85  0
         this.name = name;
 86  0
         gracefulShutdownTimeout = shutdownTimeout;
 87  0
     }
 88  
 
 89  
     public synchronized void start() throws MuleException
 90  
     {
 91  0
         gracefulShutdownTimeout = getMuleContext().getConfiguration().getShutdownTimeout();
 92  
         
 93  0
         if (workExecutorService == null)
 94  
         {
 95  0
             workExecutorService = threadingProfile.createPool(name);
 96  
         }
 97  0
     }
 98  
 
 99  
     public synchronized void dispose()
 100  
     {
 101  0
         if (workExecutorService != null)
 102  
         {
 103  
             // Disable new tasks from being submitted
 104  0
             workExecutorService.shutdown();
 105  
             try
 106  
             {
 107  
                 // Wait a while for existing tasks to terminate
 108  0
                 if (!workExecutorService.awaitTermination(gracefulShutdownTimeout, TimeUnit.MILLISECONDS))
 109  
                 {
 110  
                     // Cancel currently executing tasks and return list of pending
 111  
                     // tasks
 112  0
                     List outstanding = workExecutorService.shutdownNow();
 113  
                     // Wait a while for tasks to respond to being cancelled
 114  0
                     if (!workExecutorService.awaitTermination(FORCEFUL_SHUTDOWN_TIMEOUT, TimeUnit.MILLISECONDS))
 115  
                     {
 116  0
                         logger.warn(MessageFormat.format(
 117  
                             "Pool {0} did not terminate in time; {1} work items were cancelled.", name,
 118  
                             outstanding.isEmpty() ? "No" : Integer.toString(outstanding.size())));
 119  
                     }
 120  
                     else
 121  
                     {
 122  0
                         if (!outstanding.isEmpty())
 123  
                         {
 124  0
                             logger.warn(MessageFormat.format(
 125  
                                 "Pool {0} terminated; {1} work items were cancelled.", name,
 126  
                                 Integer.toString(outstanding.size())));
 127  
                         }
 128  
                     }
 129  
                 }
 130  
             }
 131  0
             catch (InterruptedException ie)
 132  
             {
 133  
                 // (Re-)Cancel if current thread also interrupted
 134  0
                 workExecutorService.shutdownNow();
 135  
                 // Preserve interrupt status
 136  0
                 Thread.currentThread().interrupt();
 137  
             }
 138  
             finally
 139  
             {
 140  0
                 workExecutorService = null;
 141  0
             }
 142  
         }
 143  0
     }
 144  
 
 145  
 
 146  
     // TODO
 147  
     public XATerminator getXATerminator()
 148  
     {
 149  0
         return null;
 150  
     }
 151  
 
 152  
     public void doWork(Work work) throws WorkException
 153  
     {
 154  0
         executeWork(new WorkerContext(work), syncWorkExecutor);
 155  0
     }
 156  
 
 157  
     public void doWork(Work work, long startTimeout, ExecutionContext execContext, WorkListener workListener)
 158  
         throws WorkException
 159  
     {
 160  0
         WorkerContext workWrapper = new WorkerContext(work, startTimeout, execContext, workListener);
 161  0
         workWrapper.setThreadPriority(Thread.currentThread().getPriority());
 162  0
         executeWork(workWrapper, syncWorkExecutor);
 163  0
     }
 164  
 
 165  
     public long startWork(Work work) throws WorkException
 166  
     {
 167  0
         WorkerContext workWrapper = new WorkerContext(work);
 168  0
         workWrapper.setThreadPriority(Thread.currentThread().getPriority());
 169  0
         executeWork(workWrapper, startWorkExecutor);
 170  0
         return System.currentTimeMillis() - workWrapper.getAcceptedTime();
 171  
     }
 172  
 
 173  
     public long startWork(Work work,
 174  
                           long startTimeout,
 175  
                           ExecutionContext execContext,
 176  
                           WorkListener workListener) throws WorkException
 177  
     {
 178  0
         WorkerContext workWrapper = new WorkerContext(work, startTimeout, execContext, workListener);
 179  0
         workWrapper.setThreadPriority(Thread.currentThread().getPriority());
 180  0
         executeWork(workWrapper, startWorkExecutor);
 181  0
         return System.currentTimeMillis() - workWrapper.getAcceptedTime();
 182  
     }
 183  
 
 184  
     public void scheduleWork(Work work) throws WorkException
 185  
     {
 186  0
         WorkerContext workWrapper = new WorkerContext(work);
 187  0
         workWrapper.setThreadPriority(Thread.currentThread().getPriority());
 188  0
         executeWork(workWrapper, scheduleWorkExecutor);
 189  0
     }
 190  
 
 191  
     public void scheduleWork(Work work,
 192  
                              long startTimeout,
 193  
                              ExecutionContext execContext,
 194  
                              WorkListener workListener) throws WorkException
 195  
     {
 196  0
         WorkerContext workWrapper = new WorkerContext(work, startTimeout, execContext, workListener);
 197  0
         workWrapper.setThreadPriority(Thread.currentThread().getPriority());
 198  0
         executeWork(workWrapper, scheduleWorkExecutor);
 199  0
     }
 200  
 
 201  
     /**
 202  
      * @see Executor#execute(Runnable)
 203  
      */
 204  
     public void execute(Runnable work)
 205  
     {
 206  0
         if (!isStarted())
 207  
         {
 208  0
             throw new IllegalStateException("This MuleWorkManager '" + name + "' is stopped");
 209  
         }
 210  0
         workExecutorService.execute(work);
 211  0
     }
 212  
 
 213  
     /**
 214  
      * Execute the specified Work.
 215  
      *
 216  
      * @param work Work to be executed.
 217  
      * @exception WorkException Indicates that the Work execution has been
 218  
      *                unsuccessful.
 219  
      */
 220  
     private void executeWork(WorkerContext work, WorkExecutor workExecutor) throws WorkException
 221  
     {
 222  0
         if (!isStarted())
 223  
         {
 224  0
             throw new IllegalStateException("This MuleWorkManager '" + name + "' is stopped");
 225  
         }
 226  
 
 227  
         try
 228  
         {
 229  0
             work.workAccepted(this);
 230  0
             workExecutor.doExecute(work, workExecutorService);
 231  0
             WorkException exception = work.getWorkException();
 232  0
             if (null != exception)
 233  
             {
 234  0
                 throw exception;
 235  
             }
 236  
         }
 237  0
         catch (InterruptedException e)
 238  
         {
 239  0
             WorkCompletedException wcj = new WorkCompletedException("The execution has been interrupted for WorkManager: " + name, e);
 240  0
             wcj.setErrorCode(WorkException.INTERNAL);
 241  0
             throw wcj;
 242  0
         }
 243  0
     }
 244  
 
 245  
     public boolean isStarted()
 246  
     {
 247  0
         return (workExecutorService != null && !workExecutorService.isShutdown());
 248  
     }
 249  
 
 250  
     public MuleContext getMuleContext()
 251  
     {
 252  0
         return muleContext;
 253  
     }
 254  
 
 255  
     public void setMuleContext(MuleContext muleContext)
 256  
     {
 257  0
         this.muleContext = muleContext;
 258  0
         if (this.threadingProfile != null && muleContext != null)
 259  
         {
 260  0
             threadingProfile.setMuleContext(muleContext);
 261  
         }
 262  0
     }
 263  
 }