Coverage Report - org.mule.util.queue.TransactionalQueueManager
 
Classes in this File Line Coverage Branch Coverage Complexity
TransactionalQueueManager
0%
0/108
0%
0/50
0
TransactionalQueueManager$QueueTransactionContext
0%
0/57
0%
0/32
0
 
 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.util.queue;
 8  
 
 9  
 import org.mule.api.MuleContext;
 10  
 import org.mule.api.context.MuleContextAware;
 11  
 import org.mule.util.queue.QueuePersistenceStrategy.Holder;
 12  
 import org.mule.util.xa.AbstractTransactionContext;
 13  
 import org.mule.util.xa.AbstractXAResourceManager;
 14  
 import org.mule.util.xa.ResourceManagerException;
 15  
 import org.mule.util.xa.ResourceManagerSystemException;
 16  
 
 17  
 import java.io.IOException;
 18  
 import java.util.ArrayList;
 19  
 import java.util.HashMap;
 20  
 import java.util.LinkedList;
 21  
 import java.util.List;
 22  
 import java.util.Map;
 23  
 
 24  
 import javax.transaction.xa.XAResource;
 25  
 
 26  
 /**
 27  
  * The Transactional Queue Manager is responsible for creating and Managing
 28  
  * transactional Queues. Queues can also be persistent by setting a persistence
 29  
  * strategy on the manager. Default straties are provided for Memory, Jounaling,
 30  
  * Cache and File.
 31  
  */
 32  0
 public class TransactionalQueueManager extends AbstractXAResourceManager implements QueueManager, MuleContextAware
 33  
 {
 34  
 
 35  0
     private Map<String, QueueInfo> queues = new HashMap<String, QueueInfo>();
 36  
 
 37  0
     private QueuePersistenceStrategy memoryPersistenceStrategy = new MemoryPersistenceStrategy();
 38  
     private QueuePersistenceStrategy persistenceStrategy;
 39  
 
 40  0
     private QueueConfiguration defaultQueueConfiguration = new QueueConfiguration(false);
 41  
     private MuleContext muleContext;
 42  
 
 43  
     public void setMuleContext(MuleContext context)
 44  
     {
 45  0
         this.muleContext = context;
 46  0
     }
 47  
 
 48  
     public MuleContext getMuleContext()
 49  
     {
 50  0
         return muleContext;
 51  
     }
 52  
 
 53  
     public synchronized QueueSession getQueueSession()
 54  
     {
 55  0
         return new TransactionalQueueSession(this, this);
 56  
     }
 57  
 
 58  
     public synchronized void setDefaultQueueConfiguration(QueueConfiguration config)
 59  
     {
 60  0
         this.defaultQueueConfiguration = config;
 61  0
     }
 62  
 
 63  
     public synchronized void setQueueConfiguration(String queueName, QueueConfiguration config)
 64  
     {
 65  0
         getQueue(queueName).config = config;
 66  0
     }
 67  
 
 68  
     protected synchronized QueueInfo getQueue(String name)
 69  
     {
 70  0
         QueueInfo q = queues.get(name);
 71  0
         if (q == null)
 72  
         {
 73  0
             q = new QueueInfo();
 74  0
             q.name = name;
 75  0
             q.list = new LinkedList();
 76  0
             q.config = defaultQueueConfiguration;
 77  0
             queues.put(name, q);
 78  
         }
 79  0
         return q;
 80  
     }
 81  
 
 82  
     protected void doStart() throws ResourceManagerSystemException
 83  
     {
 84  0
         if (persistenceStrategy != null)
 85  
         {
 86  
             try
 87  
             {
 88  0
                 persistenceStrategy.open();
 89  
             }
 90  0
             catch (IOException e)
 91  
             {
 92  0
                 throw new ResourceManagerSystemException(e);
 93  0
             }
 94  
         }
 95  0
     }
 96  
 
 97  
     protected boolean shutdown(int mode, long timeoutMSecs)
 98  
     {
 99  
         try
 100  
         {
 101  0
             if (persistenceStrategy != null)
 102  
             {
 103  0
                 persistenceStrategy.close();
 104  
             }
 105  
         }
 106  0
         catch (IOException e)
 107  
         {
 108  
             // TODO MULE-863: What should we really do?
 109  0
             logger.error("Error closing persistent store", e);
 110  0
         }
 111  
         // Clear queues on shutdown to avoid duplicate entries on warm restarts (MULE-3678)
 112  0
         synchronized (this)
 113  
         {
 114  0
             queues.clear();
 115  0
         }
 116  0
         return super.shutdown(mode, timeoutMSecs);
 117  
     }
 118  
 
 119  
     protected void recover() throws ResourceManagerSystemException
 120  
     {
 121  0
         if (persistenceStrategy != null)
 122  
         {
 123  
             try
 124  
             {
 125  0
                 List msgs = persistenceStrategy.restore();
 126  0
                 for (Object msg : msgs)
 127  
                 {
 128  0
                     Holder h = (Holder) msg;
 129  0
                     getQueue(h.getQueue()).putNow(h.getId());
 130  0
                 }
 131  
             }
 132  0
             catch (Exception e)
 133  
             {
 134  0
                 throw new ResourceManagerSystemException(e);
 135  0
             }
 136  
         }
 137  0
     }
 138  
 
 139  
     protected AbstractTransactionContext createTransactionContext(Object session)
 140  
     {
 141  0
         return new QueueTransactionContext();
 142  
     }
 143  
 
 144  
     protected void doBegin(AbstractTransactionContext context)
 145  
     {
 146  
         // Nothing special to do
 147  0
     }
 148  
 
 149  
     protected int doPrepare(AbstractTransactionContext context)
 150  
     {
 151  0
         return XAResource.XA_OK;
 152  
     }
 153  
 
 154  
     protected void doCommit(AbstractTransactionContext context) throws ResourceManagerException
 155  
     {
 156  0
         QueueTransactionContext ctx = (QueueTransactionContext) context;
 157  
         try
 158  
         {
 159  0
             if (ctx.added != null)
 160  
             {
 161  0
                 for (Object o : ctx.added.entrySet())
 162  
                 {
 163  0
                     Map.Entry entry = (Map.Entry) o;
 164  0
                     QueueInfo queue = (QueueInfo) entry.getKey();
 165  0
                     List queueAdded = (List) entry.getValue();
 166  0
                     if (queueAdded != null && queueAdded.size() > 0)
 167  
                     {
 168  0
                         for (Object object : queueAdded)
 169  
                         {
 170  0
                             Object id = doStore(queue, object);
 171  0
                             queue.putNow(id);
 172  0
                         }
 173  
                     }
 174  0
                 }
 175  
             }
 176  0
             if (ctx.removed != null)
 177  
             {
 178  0
                 for (Object o : ctx.removed.entrySet())
 179  
                 {
 180  0
                     Map.Entry entry = (Map.Entry) o;
 181  0
                     QueueInfo queue = (QueueInfo) entry.getKey();
 182  0
                     List queueRemoved = (List) entry.getValue();
 183  0
                     if (queueRemoved != null && queueRemoved.size() > 0)
 184  
                     {
 185  0
                         for (Object id : queueRemoved)
 186  
                         {
 187  0
                             doRemove(queue, id);
 188  
                         }
 189  
                     }
 190  0
                 }
 191  
             }
 192  
         }
 193  0
         catch (Exception e)
 194  
         {
 195  
             // throw new ResourceManagerException("Could not commit
 196  
             // transaction", e);
 197  
             // TODO: add an i18n Message
 198  0
             throw new ResourceManagerException(e);
 199  
         }
 200  
         finally
 201  
         {
 202  0
             ctx.added = null;
 203  0
             ctx.removed = null;
 204  0
         }
 205  0
     }
 206  
 
 207  
     protected Object doStore(QueueInfo queue, Object object) throws IOException
 208  
     {
 209  0
         QueuePersistenceStrategy ps = (queue.config.persistent)
 210  
                         ? persistenceStrategy : memoryPersistenceStrategy;
 211  0
         Object id = ps.store(queue.name, object);
 212  0
         return id;
 213  
     }
 214  
 
 215  
     protected void doRemove(QueueInfo queue, Object id) throws IOException
 216  
     {
 217  0
         QueuePersistenceStrategy ps = (queue.config.persistent)
 218  
                         ? persistenceStrategy : memoryPersistenceStrategy;
 219  0
         ps.remove(queue.name, id);
 220  0
     }
 221  
 
 222  
     protected Object doLoad(QueueInfo queue, Object id) throws IOException
 223  
     {
 224  0
         QueuePersistenceStrategy ps = (queue.config.persistent)
 225  
                         ? persistenceStrategy : memoryPersistenceStrategy;
 226  0
         Object obj = ps.load(queue.name, id);
 227  0
         return obj;
 228  
     }
 229  
 
 230  
     protected void doRollback(AbstractTransactionContext context) throws ResourceManagerException
 231  
     {
 232  0
         QueueTransactionContext ctx = (QueueTransactionContext) context;
 233  0
         if (ctx.removed != null)
 234  
         {
 235  0
             for (Object o : ctx.removed.entrySet())
 236  
             {
 237  0
                 Map.Entry entry = (Map.Entry) o;
 238  0
                 QueueInfo queue = (QueueInfo) entry.getKey();
 239  0
                 List queueRemoved = (List) entry.getValue();
 240  0
                 if (queueRemoved != null && queueRemoved.size() > 0)
 241  
                 {
 242  0
                     for (Object id : queueRemoved)
 243  
                     {
 244  0
                         queue.putNow(id);
 245  
                     }
 246  
                 }
 247  0
             }
 248  
         }
 249  0
         ctx.added = null;
 250  0
         ctx.removed = null;
 251  0
     }
 252  
 
 253  0
     protected class QueueTransactionContext extends AbstractTransactionContext
 254  
     {
 255  
         protected Map added;
 256  
         protected Map removed;
 257  
 
 258  
         @SuppressWarnings("unchecked")
 259  
         public boolean offer(QueueInfo queue, Object item, long timeout) throws InterruptedException
 260  
         {
 261  0
             readOnly = false;
 262  0
             if (added == null)
 263  
             {
 264  0
                 added = new HashMap();
 265  
             }
 266  0
             List queueAdded = (List) added.get(queue);
 267  0
             if (queueAdded == null)
 268  
             {
 269  0
                 queueAdded = new ArrayList();
 270  0
                 added.put(queue, queueAdded);
 271  
             }
 272  
             // wait for enough room
 273  0
             if (queue.offer(null, queueAdded.size(), timeout))
 274  
             {
 275  0
                 queueAdded.add(item);
 276  0
                 return true;
 277  
             }
 278  
             else
 279  
             {
 280  0
                 return false;
 281  
             }
 282  
         }
 283  
 
 284  
         @SuppressWarnings("unchecked")
 285  
         public void untake(QueueInfo queue, Object item) throws InterruptedException
 286  
         {
 287  0
             readOnly = false;
 288  0
             if (added == null)
 289  
             {
 290  0
                 added = new HashMap();
 291  
             }
 292  0
             List queueAdded = (List) added.get(queue);
 293  0
             if (queueAdded == null)
 294  
             {
 295  0
                 queueAdded = new ArrayList();
 296  0
                 added.put(queue, queueAdded);
 297  
             }
 298  0
             queueAdded.add(item);
 299  0
         }
 300  
         
 301  
         @SuppressWarnings("unchecked")
 302  
         public Object poll(QueueInfo queue, long timeout) throws IOException, InterruptedException
 303  
         {
 304  0
             readOnly = false;
 305  0
             if (added != null)
 306  
             {
 307  0
                 List queueAdded = (List)added.get(queue);
 308  0
                 if (queueAdded != null)
 309  
                 {
 310  0
                     return queueAdded.remove(queueAdded.size() - 1);
 311  
                 }
 312  
             }
 313  
             Object o;
 314  
             try
 315  
             {
 316  0
                 o = queue.poll(timeout);
 317  
             }
 318  0
             catch (InterruptedException e)
 319  
             {
 320  0
                 if (muleContext.isStopping())
 321  
                 {
 322  0
                     throw e;
 323  
                 }
 324  
                 // if disposing, ignore
 325  0
                 return null;
 326  0
             }
 327  0
             if (o != null)
 328  
             {
 329  0
                 if (removed == null)
 330  
                 {
 331  0
                     removed = new HashMap();
 332  
                 }
 333  0
                 List queueRemoved = (List) removed.get(queue);
 334  0
                 if (queueRemoved == null)
 335  
                 {
 336  0
                     queueRemoved = new ArrayList();
 337  0
                     removed.put(queue, queueRemoved);
 338  
                 }
 339  0
                 queueRemoved.add(o);
 340  0
                 o = doLoad(queue, o);
 341  
             }
 342  0
             return o;
 343  
         }
 344  
 
 345  
         public Object peek(QueueInfo queue) throws IOException, InterruptedException
 346  
         {
 347  0
             readOnly = false;
 348  0
             if (added != null)
 349  
             {
 350  0
                 List queueAdded = (List) added.get(queue);
 351  0
                 if (queueAdded != null)
 352  
                 {
 353  0
                     return queueAdded.get(queueAdded.size() - 1);
 354  
                 }
 355  
             }
 356  0
             Object o = queue.peek();
 357  0
             if (o != null)
 358  
             {
 359  0
                 o = doLoad(queue, o);
 360  
             }
 361  0
             return o;
 362  
         }
 363  
 
 364  
         public int size(QueueInfo queue)
 365  
         {
 366  0
             int sz = queue.list.size();
 367  0
             if (added != null)
 368  
             {
 369  0
                 List queueAdded = (List) added.get(queue);
 370  0
                 if (queueAdded != null)
 371  
                 {
 372  0
                     sz += queueAdded.size();
 373  
                 }
 374  
             }
 375  0
             return sz;
 376  
         }
 377  
 
 378  
     }
 379  
 
 380  
     public QueuePersistenceStrategy getPersistenceStrategy()
 381  
     {
 382  0
         return persistenceStrategy;
 383  
     }
 384  
 
 385  
     public void setPersistenceStrategy(QueuePersistenceStrategy persistenceStrategy)
 386  
     {
 387  0
         if (operationMode != OPERATION_MODE_STOPPED)
 388  
         {
 389  0
             throw new IllegalStateException();
 390  
         }
 391  0
         this.persistenceStrategy = persistenceStrategy;
 392  0
     }
 393  
 
 394  
     public QueuePersistenceStrategy getMemoryPersistenceStrategy()
 395  
     {
 396  0
         return memoryPersistenceStrategy;
 397  
     }
 398  
 
 399  
     public void setMemoryPersistenceStrategy(QueuePersistenceStrategy memoryPersistenceStrategy)
 400  
     {
 401  0
         if (operationMode != OPERATION_MODE_STOPPED)
 402  
         {
 403  0
             throw new IllegalStateException();
 404  
         }
 405  0
         this.memoryPersistenceStrategy = memoryPersistenceStrategy;
 406  0
     }
 407  
 
 408  
 }