Coverage Report - org.mule.impl.work.MuleWorkManager
 
Classes in this File Line Coverage Branch Coverage Complexity
MuleWorkManager
64%
45/70
50%
9/18
2
 
 1  
 /*
 2  
  * $Id: MuleWorkManager.java 10415 2008-01-21 10:46:37Z 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.impl.work;
 29  
 
 30  
 import org.mule.MuleManager;
 31  
 import org.mule.config.ThreadingProfile;
 32  
 import org.mule.umo.UMOException;
 33  
 import org.mule.umo.manager.UMOWorkManager;
 34  
 
 35  
 import java.util.List;
 36  
 
 37  
 import javax.resource.spi.XATerminator;
 38  
 import javax.resource.spi.work.ExecutionContext;
 39  
 import javax.resource.spi.work.Work;
 40  
 import javax.resource.spi.work.WorkCompletedException;
 41  
 import javax.resource.spi.work.WorkException;
 42  
 import javax.resource.spi.work.WorkListener;
 43  
 
 44  
 import edu.emory.mathcs.backport.java.util.concurrent.Executor;
 45  
 import edu.emory.mathcs.backport.java.util.concurrent.ExecutorService;
 46  
 import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
 47  
 
 48  
 import org.apache.commons.logging.Log;
 49  
 import org.apache.commons.logging.LogFactory;
 50  
 
 51  
 /**
 52  
  * <code>MuleWorkManager</code> is a JCA Work manager implementation used to manage
 53  
  * thread allocation for Mule components and connectors. This code has been adapted
 54  
  * from the Geronimo implementation.
 55  
  */
 56  
 public class MuleWorkManager implements UMOWorkManager
 57  
 {
 58  
     /**
 59  
      * logger used by this class
 60  
      */
 61  4
     protected static final Log logger = LogFactory.getLog(MuleWorkManager.class);
 62  
 
 63  
     /**
 64  
      * Graceful shutdown delay
 65  
      */
 66  
     private static final long SHUTDOWN_TIMEOUT = 5000L;
 67  
 
 68  
     /**
 69  
      * The ThreadingProfile used for creation of the underlying ExecutorService
 70  
      */
 71  
     private final ThreadingProfile threadingProfile;
 72  
 
 73  
     /**
 74  
      * The actual pool of threads used by this MuleWorkManager to process the Work
 75  
      * instances submitted via the (do,start,schedule)Work methods.
 76  
      */
 77  
     private volatile ExecutorService workExecutorService;
 78  
     private final String name;
 79  
 
 80  
     /**
 81  
      * Various policies used for work execution
 82  
      */
 83  110
     private final WorkExecutor scheduleWorkExecutor = new ScheduleWorkExecutor();
 84  110
     private final WorkExecutor startWorkExecutor = new StartWorkExecutor();
 85  110
     private final WorkExecutor syncWorkExecutor = new SyncWorkExecutor();
 86  
 
 87  
     public MuleWorkManager()
 88  
     {
 89  6
         this(MuleManager.getConfiguration().getDefaultThreadingProfile(), null);
 90  6
     }
 91  
 
 92  
     public MuleWorkManager(ThreadingProfile profile, String name)
 93  
     {
 94  110
         super();
 95  
 
 96  110
         if (name == null)
 97  
         {
 98  6
             name = "WorkManager#" + hashCode();
 99  
         }
 100  
 
 101  110
         this.threadingProfile = profile;
 102  110
         this.name = name;
 103  110
     }
 104  
 
 105  
     public synchronized void start() throws UMOException
 106  
     {
 107  98
         if (workExecutorService == null)
 108  
         {
 109  98
             workExecutorService = threadingProfile.createPool(name);
 110  
         }
 111  98
     }
 112  
 
 113  
     public synchronized void stop() throws UMOException
 114  
     {
 115  136
         if (workExecutorService != null)
 116  
         {
 117  
             try
 118  
             {
 119  
                 // Cancel currently executing tasks
 120  94
                 List outstanding = workExecutorService.shutdownNow();
 121  
 
 122  
                 // Wait a while for existing tasks to terminate
 123  94
                 if (!workExecutorService.awaitTermination(SHUTDOWN_TIMEOUT, TimeUnit.MILLISECONDS))
 124  
                 {
 125  0
                     logger.warn("Pool " + name + " did not terminate in time; " + outstanding.size()
 126  
                                     + " work items were cancelled.");
 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  94
                 workExecutorService = null;
 139  94
             }
 140  
         }
 141  136
     }
 142  
 
 143  
     public void dispose()
 144  
     {
 145  
         try
 146  
         {
 147  98
             stop();
 148  
         }
 149  0
         catch (UMOException e)
 150  
         {
 151  
             // Ok, stop failed but since we're being disposed anyway just log and continue
 152  0
             logger.warn("Error while disposing Work Manager: " + e.getMessage(), e);
 153  98
         }
 154  98
     }
 155  
 
 156  
     // TODO
 157  
     public XATerminator getXATerminator()
 158  
     {
 159  0
         return null;
 160  
     }
 161  
 
 162  
     /*
 163  
      * (non-Javadoc)
 164  
      * 
 165  
      * @see javax.resource.spi.work.MuleWorkManager#doWork(javax.resource.spi.work.Work)
 166  
      */
 167  
     public void doWork(Work work) throws WorkException
 168  
     {
 169  2
         executeWork(new WorkerContext(work), syncWorkExecutor);
 170  2
     }
 171  
 
 172  
     /*
 173  
      * (non-Javadoc)
 174  
      * 
 175  
      * @see javax.resource.spi.work.MuleWorkManager#doWork(javax.resource.spi.work.Work,
 176  
      *      long, javax.resource.spi.work.ExecutionContext,
 177  
      *      javax.resource.spi.work.WorkListener)
 178  
      */
 179  
     public void doWork(Work work, long startTimeout, ExecutionContext execContext, WorkListener workListener)
 180  
         throws WorkException
 181  
     {
 182  0
         WorkerContext workWrapper = new WorkerContext(work, startTimeout, execContext, workListener);
 183  0
         workWrapper.setThreadPriority(Thread.currentThread().getPriority());
 184  0
         executeWork(workWrapper, syncWorkExecutor);
 185  0
     }
 186  
 
 187  
     /*
 188  
      * (non-Javadoc)
 189  
      * 
 190  
      * @see javax.resource.spi.work.MuleWorkManager#startWork(javax.resource.spi.work.Work)
 191  
      */
 192  
     public long startWork(Work work) throws WorkException
 193  
     {
 194  2
         WorkerContext workWrapper = new WorkerContext(work);
 195  2
         workWrapper.setThreadPriority(Thread.currentThread().getPriority());
 196  2
         executeWork(workWrapper, startWorkExecutor);
 197  2
         return System.currentTimeMillis() - workWrapper.getAcceptedTime();
 198  
     }
 199  
 
 200  
     /*
 201  
      * (non-Javadoc)
 202  
      * 
 203  
      * @see javax.resource.spi.work.MuleWorkManager#startWork(javax.resource.spi.work.Work,
 204  
      *      long, javax.resource.spi.work.ExecutionContext,
 205  
      *      javax.resource.spi.work.WorkListener)
 206  
      */
 207  
     public long startWork(Work work,
 208  
                           long startTimeout,
 209  
                           ExecutionContext execContext,
 210  
                           WorkListener workListener) throws WorkException
 211  
     {
 212  0
         WorkerContext workWrapper = new WorkerContext(work, startTimeout, execContext, workListener);
 213  0
         workWrapper.setThreadPriority(Thread.currentThread().getPriority());
 214  0
         executeWork(workWrapper, startWorkExecutor);
 215  0
         return System.currentTimeMillis() - workWrapper.getAcceptedTime();
 216  
     }
 217  
 
 218  
     /*
 219  
      * (non-Javadoc)
 220  
      * 
 221  
      * @see javax.resource.spi.work.MuleWorkManager#scheduleWork(javax.resource.spi.work.Work)
 222  
      */
 223  
     public void scheduleWork(Work work) throws WorkException
 224  
     {
 225  2
         WorkerContext workWrapper = new WorkerContext(work);
 226  2
         workWrapper.setThreadPriority(Thread.currentThread().getPriority());
 227  2
         executeWork(workWrapper, scheduleWorkExecutor);
 228  2
     }
 229  
 
 230  
     /*
 231  
      * (non-Javadoc)
 232  
      * 
 233  
      * @see javax.resource.spi.work.MuleWorkManager#scheduleWork(javax.resource.spi.work.Work,
 234  
      *      long, javax.resource.spi.work.ExecutionContext,
 235  
      *      javax.resource.spi.work.WorkListener)
 236  
      */
 237  
     public void scheduleWork(Work work,
 238  
                              long startTimeout,
 239  
                              ExecutionContext execContext,
 240  
                              WorkListener workListener) throws WorkException
 241  
     {
 242  66
         WorkerContext workWrapper = new WorkerContext(work, startTimeout, execContext, workListener);
 243  66
         workWrapper.setThreadPriority(Thread.currentThread().getPriority());
 244  66
         executeWork(workWrapper, scheduleWorkExecutor);
 245  66
     }
 246  
 
 247  
     /**
 248  
      * @see Executor#execute(Runnable)
 249  
      */
 250  
     public void execute(Runnable work)
 251  
     {
 252  0
         if (workExecutorService == null || workExecutorService.isShutdown())
 253  
         {
 254  0
             throw new IllegalStateException("This MuleWorkManager is stopped");
 255  
         }
 256  
 
 257  0
         workExecutorService.execute(work);
 258  0
     }
 259  
 
 260  
     /**
 261  
      * Execute the specified Work.
 262  
      * 
 263  
      * @param work Work to be executed.
 264  
      * @exception WorkException Indicates that the Work execution has been
 265  
      *                unsuccessful.
 266  
      */
 267  
     private void executeWork(WorkerContext work, WorkExecutor workExecutor) throws WorkException
 268  
     {
 269  72
         if (workExecutorService == null || workExecutorService.isShutdown())
 270  
         {
 271  0
             throw new IllegalStateException("This MuleWorkManager is stopped");
 272  
         }
 273  
 
 274  
         try
 275  
         {
 276  72
             work.workAccepted(this);
 277  72
             workExecutor.doExecute(work, workExecutorService);
 278  72
             WorkException exception = work.getWorkException();
 279  72
             if (null != exception)
 280  
             {
 281  0
                 throw exception;
 282  
             }
 283  
         }
 284  0
         catch (InterruptedException e)
 285  
         {
 286  0
             WorkCompletedException wcj = new WorkCompletedException("The execution has been interrupted.", e);
 287  0
             wcj.setErrorCode(WorkException.INTERNAL);
 288  0
             throw wcj;
 289  72
         }
 290  72
     }
 291  
 
 292  
 }