Coverage Report - org.mule.work.MuleWorkManager
 
Classes in this File Line Coverage Branch Coverage Complexity
MuleWorkManager
61%
40/66
41%
9/22
2.333
 
 1  
 /*
 2  
  * $Id: MuleWorkManager.java 11517 2008-03-31 21:34:19Z dirk.olmes $
 3  
  * --------------------------------------------------------------------------------------
 4  
  * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
 5  
  *
 6  
  * The software in this package is published under the terms of the CPAL v1.0
 7  
  * license, a copy of which has been included with this distribution in the
 8  
  * LICENSE.txt file.
 9  
  */
 10  
 
 11  
 /**
 12  
  *
 13  
  * Copyright 2004 The Apache Software Foundation
 14  
  *
 15  
  *  Licensed under the Apache License, Version 2.0 (the "License");
 16  
  *  you may not use this file except in compliance with the License.
 17  
  *  You may obtain a copy of the License at
 18  
  *
 19  
  *     http://www.apache.org/licenses/LICENSE-2.0
 20  
  *
 21  
  *  Unless required by applicable law or agreed to in writing, software
 22  
  *  distributed under the License is distributed on an "AS IS" BASIS,
 23  
  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 24  
  *  See the License for the specific language governing permissions and
 25  
  *  limitations under the License.
 26  
  */
 27  
 
 28  
 package org.mule.work;
 29  
 
 30  
 import org.mule.api.MuleException;
 31  
 import org.mule.api.config.ThreadingProfile;
 32  
 import org.mule.api.context.WorkManager;
 33  
 import org.mule.api.work.WorkExecutor;
 34  
 
 35  
 import java.text.MessageFormat;
 36  
 import java.util.List;
 37  
 
 38  
 import javax.resource.spi.XATerminator;
 39  
 import javax.resource.spi.work.ExecutionContext;
 40  
 import javax.resource.spi.work.Work;
 41  
 import javax.resource.spi.work.WorkCompletedException;
 42  
 import javax.resource.spi.work.WorkException;
 43  
 import javax.resource.spi.work.WorkListener;
 44  
 
 45  
 import edu.emory.mathcs.backport.java.util.concurrent.Executor;
 46  
 import edu.emory.mathcs.backport.java.util.concurrent.ExecutorService;
 47  
 import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
 48  
 
 49  
 import org.apache.commons.logging.Log;
 50  
 import org.apache.commons.logging.LogFactory;
 51  
 
 52  
 /**
 53  
  * <code>MuleWorkManager</code> is a JCA Work manager implementation used to manage
 54  
  * thread allocation for Mule components and connectors. This code has been adapted
 55  
  * from the Geronimo implementation.
 56  
  */
 57  
 public class MuleWorkManager implements WorkManager
 58  
 {
 59  
     /**
 60  
      * logger used by this class
 61  
      */
 62  2
     protected static final Log logger = LogFactory.getLog(MuleWorkManager.class);
 63  
 
 64  
     /**
 65  
      * Graceful shutdown delay
 66  
      */
 67  
     private static final long SHUTDOWN_TIMEOUT = 5000L;
 68  
 
 69  
     /**
 70  
      * The ThreadingProfile used for creation of the underlying ExecutorService
 71  
      */
 72  
     private final ThreadingProfile threadingProfile;
 73  
 
 74  
     /**
 75  
      * The actual pool of threads used by this MuleWorkManager to process the Work
 76  
      * instances submitted via the (do,start,schedule)Work methods.
 77  
      */
 78  
     private volatile ExecutorService workExecutorService;
 79  
     private final String name;
 80  
 
 81  
     /**
 82  
      * Various policies used for work execution
 83  
      */
 84  2504
     private final WorkExecutor scheduleWorkExecutor = new ScheduleWorkExecutor();
 85  2504
     private final WorkExecutor startWorkExecutor = new StartWorkExecutor();
 86  2504
     private final WorkExecutor syncWorkExecutor = new SyncWorkExecutor();
 87  
 
 88  
     public MuleWorkManager(ThreadingProfile profile, String name)
 89  
     {
 90  2504
         super();
 91  
 
 92  2504
         if (name == null)
 93  
         {
 94  6
             name = "WorkManager#" + hashCode();
 95  
         }
 96  
 
 97  2504
         this.threadingProfile = profile;
 98  2504
         this.name = name;
 99  2504
     }
 100  
 
 101  
     public synchronized void start() throws MuleException
 102  
     {
 103  2124
         if (workExecutorService == null)
 104  
         {
 105  2124
             workExecutorService = threadingProfile.createPool(name);
 106  
         }
 107  2124
     }
 108  
 
 109  
     public synchronized void dispose()
 110  
     {
 111  1250
         if (workExecutorService != null)
 112  
         {
 113  
             try
 114  
             {
 115  
                 // Cancel currently executing tasks
 116  1248
                 List outstanding = workExecutorService.shutdownNow();
 117  
 
 118  
                 // Wait a while for existing tasks to terminate
 119  1248
                 if (!workExecutorService.awaitTermination(SHUTDOWN_TIMEOUT, TimeUnit.MILLISECONDS))
 120  
                 {
 121  0
                     if (logger.isWarnEnabled())
 122  
                     {
 123  0
                         logger.warn(MessageFormat.format(
 124  
                                 "Pool {0} did not terminate in time; {1} work items were cancelled.",
 125  
                                 new Object[] {name, outstanding.isEmpty() ? "No" : Integer.toString(outstanding.size())}));
 126  
                     }
 127  
                 }
 128  
             }
 129  0
             catch (InterruptedException ie)
 130  
             {
 131  
                 // (Re-)Cancel if current thread also interrupted
 132  0
                 workExecutorService.shutdownNow();
 133  
                 // Preserve interrupt status
 134  0
                 Thread.currentThread().interrupt();
 135  
             }
 136  
             finally
 137  
             {
 138  1248
                 workExecutorService = null;
 139  1248
             }
 140  
         }
 141  1250
     }
 142  
 
 143  
 
 144  
     // TODO
 145  
     public XATerminator getXATerminator()
 146  
     {
 147  0
         return null;
 148  
     }
 149  
 
 150  
     /*
 151  
      * (non-Javadoc)
 152  
      *
 153  
      * @see javax.resource.spi.work.MuleWorkManager#doWork(javax.resource.spi.work.Work)
 154  
      */
 155  
     public void doWork(Work work) throws WorkException
 156  
     {
 157  2
         executeWork(new WorkerContext(work), syncWorkExecutor);
 158  2
     }
 159  
 
 160  
     /*
 161  
      * (non-Javadoc)
 162  
      *
 163  
      * @see javax.resource.spi.work.MuleWorkManager#doWork(javax.resource.spi.work.Work,
 164  
      *      long, javax.resource.spi.work.ExecutionContext,
 165  
      *      javax.resource.spi.work.WorkListener)
 166  
      */
 167  
     public void doWork(Work work, long startTimeout, ExecutionContext execContext, WorkListener workListener)
 168  
         throws WorkException
 169  
     {
 170  0
         WorkerContext workWrapper = new WorkerContext(work, startTimeout, execContext, workListener);
 171  0
         workWrapper.setThreadPriority(Thread.currentThread().getPriority());
 172  0
         executeWork(workWrapper, syncWorkExecutor);
 173  0
     }
 174  
 
 175  
     /*
 176  
      * (non-Javadoc)
 177  
      *
 178  
      * @see javax.resource.spi.work.MuleWorkManager#startWork(javax.resource.spi.work.Work)
 179  
      */
 180  
     public long startWork(Work work) throws WorkException
 181  
     {
 182  2
         WorkerContext workWrapper = new WorkerContext(work);
 183  2
         workWrapper.setThreadPriority(Thread.currentThread().getPriority());
 184  2
         executeWork(workWrapper, startWorkExecutor);
 185  2
         return System.currentTimeMillis() - workWrapper.getAcceptedTime();
 186  
     }
 187  
 
 188  
     /*
 189  
      * (non-Javadoc)
 190  
      *
 191  
      * @see javax.resource.spi.work.MuleWorkManager#startWork(javax.resource.spi.work.Work,
 192  
      *      long, javax.resource.spi.work.ExecutionContext,
 193  
      *      javax.resource.spi.work.WorkListener)
 194  
      */
 195  
     public long startWork(Work work,
 196  
                           long startTimeout,
 197  
                           ExecutionContext execContext,
 198  
                           WorkListener workListener) throws WorkException
 199  
     {
 200  0
         WorkerContext workWrapper = new WorkerContext(work, startTimeout, execContext, workListener);
 201  0
         workWrapper.setThreadPriority(Thread.currentThread().getPriority());
 202  0
         executeWork(workWrapper, startWorkExecutor);
 203  0
         return System.currentTimeMillis() - workWrapper.getAcceptedTime();
 204  
     }
 205  
 
 206  
     /*
 207  
      * (non-Javadoc)
 208  
      *
 209  
      * @see javax.resource.spi.work.MuleWorkManager#scheduleWork(javax.resource.spi.work.Work)
 210  
      */
 211  
     public void scheduleWork(Work work) throws WorkException
 212  
     {
 213  2
         WorkerContext workWrapper = new WorkerContext(work);
 214  2
         workWrapper.setThreadPriority(Thread.currentThread().getPriority());
 215  2
         executeWork(workWrapper, scheduleWorkExecutor);
 216  2
     }
 217  
 
 218  
     /*
 219  
      * (non-Javadoc)
 220  
      *
 221  
      * @see javax.resource.spi.work.MuleWorkManager#scheduleWork(javax.resource.spi.work.Work,
 222  
      *      long, javax.resource.spi.work.ExecutionContext,
 223  
      *      javax.resource.spi.work.WorkListener)
 224  
      */
 225  
     public void scheduleWork(Work work,
 226  
                              long startTimeout,
 227  
                              ExecutionContext execContext,
 228  
                              WorkListener workListener) throws WorkException
 229  
     {
 230  1174
         WorkerContext workWrapper = new WorkerContext(work, startTimeout, execContext, workListener);
 231  1174
         workWrapper.setThreadPriority(Thread.currentThread().getPriority());
 232  1174
         executeWork(workWrapper, scheduleWorkExecutor);
 233  1174
     }
 234  
 
 235  
     /**
 236  
      * @see Executor#execute(Runnable)
 237  
      */
 238  
     public void execute(Runnable work)
 239  
     {
 240  0
         if (workExecutorService == null)
 241  
         {
 242  0
             throw new IllegalStateException("This MuleWorkManager '" + name + "' was never started");
 243  
         }
 244  0
         else if (workExecutorService.isShutdown())
 245  
         {
 246  0
             throw new IllegalStateException("This MuleWorkManager '" + name + "' is stopped");
 247  
         }
 248  
 
 249  0
         workExecutorService.execute(work);
 250  0
     }
 251  
 
 252  
     /**
 253  
      * Execute the specified Work.
 254  
      *
 255  
      * @param work Work to be executed.
 256  
      * @exception WorkException Indicates that the Work execution has been
 257  
      *                unsuccessful.
 258  
      */
 259  
     private void executeWork(WorkerContext work, WorkExecutor workExecutor) throws WorkException
 260  
     {
 261  1180
         if (workExecutorService == null || workExecutorService.isShutdown())
 262  
         {
 263  0
             throw new IllegalStateException("This MuleWorkManager '" + name + "' is stopped");
 264  
         }
 265  
 
 266  
         try
 267  
         {
 268  1180
             work.workAccepted(this);
 269  1180
             workExecutor.doExecute(work, workExecutorService);
 270  1180
             WorkException exception = work.getWorkException();
 271  1180
             if (null != exception)
 272  
             {
 273  0
                 throw exception;
 274  
             }
 275  
         }
 276  0
         catch (InterruptedException e)
 277  
         {
 278  0
             WorkCompletedException wcj = new WorkCompletedException("The execution has been interrupted for WorkManager: " + name, e);
 279  0
             wcj.setErrorCode(WorkException.INTERNAL);
 280  0
             throw wcj;
 281  1180
         }
 282  1180
     }
 283  
 
 284  
 }