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