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