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