Coverage Report - org.mule.providers.jms.xa.ConnectionFactoryWrapper
 
Classes in this File Line Coverage Branch Coverage Complexity
ConnectionFactoryWrapper
0%
0/23
0%
0/6
2.812
ConnectionFactoryWrapper$ConnectionInvocationHandler
0%
0/17
0%
0/7
2.812
ConnectionFactoryWrapper$ConnectionInvocationHandler$SessionInvocationHandler
0%
0/31
0%
0/18
2.812
ConnectionFactoryWrapper$ConnectionInvocationHandler$SessionInvocationHandler$ConsumerProducerInvocationHandler
0%
0/8
0%
0/2
2.812
ConnectionFactoryWrapper$ConnectionInvocationHandler$SessionInvocationHandler$XAResourceInvocationHandler
0%
0/12
0%
0/4
2.812
 
 1  
 /*
 2  
  * $Id: ConnectionFactoryWrapper.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.providers.jms.xa;
 12  
 
 13  
 import java.lang.reflect.InvocationHandler;
 14  
 import java.lang.reflect.InvocationTargetException;
 15  
 import java.lang.reflect.Method;
 16  
 import java.lang.reflect.Proxy;
 17  
 
 18  
 import javax.jms.Connection;
 19  
 import javax.jms.ConnectionFactory;
 20  
 import javax.jms.JMSException;
 21  
 import javax.jms.MessageConsumer;
 22  
 import javax.jms.MessageProducer;
 23  
 import javax.jms.QueueConnection;
 24  
 import javax.jms.QueueConnectionFactory;
 25  
 import javax.jms.QueueReceiver;
 26  
 import javax.jms.QueueSender;
 27  
 import javax.jms.QueueSession;
 28  
 import javax.jms.Session;
 29  
 import javax.jms.TopicConnection;
 30  
 import javax.jms.TopicConnectionFactory;
 31  
 import javax.jms.TopicPublisher;
 32  
 import javax.jms.TopicSession;
 33  
 import javax.jms.TopicSubscriber;
 34  
 import javax.jms.XAConnection;
 35  
 import javax.jms.XAConnectionFactory;
 36  
 import javax.jms.XAQueueConnection;
 37  
 import javax.jms.XAQueueConnectionFactory;
 38  
 import javax.jms.XAQueueSession;
 39  
 import javax.jms.XASession;
 40  
 import javax.jms.XATopicConnection;
 41  
 import javax.jms.XATopicConnectionFactory;
 42  
 import javax.jms.XATopicSession;
 43  
 import javax.transaction.Transaction;
 44  
 import javax.transaction.TransactionManager;
 45  
 import javax.transaction.xa.XAResource;
 46  
 
 47  
 import org.apache.commons.logging.Log;
 48  
 import org.apache.commons.logging.LogFactory;
 49  
 
 50  
 public class ConnectionFactoryWrapper
 51  
     implements ConnectionFactory, QueueConnectionFactory, TopicConnectionFactory
 52  
 {
 53  
     /**
 54  
      * logger used by this class
 55  
      */
 56  0
     protected static final Log logger = LogFactory.getLog(ConnectionFactoryWrapper.class);
 57  
 
 58  
     protected final Object factory;
 59  
     protected final TransactionManager tm;
 60  
 
 61  
     public ConnectionFactoryWrapper(Object factory, TransactionManager tm)
 62  0
     {
 63  0
         this.factory = factory;
 64  0
         this.tm = tm;
 65  0
     }
 66  
 
 67  
     /*
 68  
      * (non-Javadoc)
 69  
      * 
 70  
      * @see javax.jms.ConnectionFactory#createConnection()
 71  
      */
 72  
     public Connection createConnection() throws JMSException
 73  
     {
 74  0
         XAConnection xac = ((XAConnectionFactory)factory).createXAConnection();
 75  0
         Connection proxy = (Connection)Proxy.newProxyInstance(Connection.class.getClassLoader(),
 76  
             new Class[]{Connection.class}, new ConnectionInvocationHandler(xac));
 77  0
         return proxy;
 78  
     }
 79  
 
 80  
     /*
 81  
      * (non-Javadoc)
 82  
      * 
 83  
      * @see javax.jms.ConnectionFactory#createConnection(java.lang.String,
 84  
      *      java.lang.String)
 85  
      */
 86  
     public Connection createConnection(String username, String password) throws JMSException
 87  
     {
 88  0
         XAConnection xac = ((XAConnectionFactory)factory).createXAConnection(username, password);
 89  0
         Connection proxy = (Connection)Proxy.newProxyInstance(Connection.class.getClassLoader(),
 90  
             new Class[]{Connection.class}, new ConnectionInvocationHandler(xac));
 91  0
         return proxy;
 92  
     }
 93  
 
 94  
     /*
 95  
      * (non-Javadoc)
 96  
      * 
 97  
      * @see javax.jms.QueueConnectionFactory#createQueueConnection()
 98  
      */
 99  
     public QueueConnection createQueueConnection() throws JMSException
 100  
     {
 101  0
         XAQueueConnection xaqc = ((XAQueueConnectionFactory)factory).createXAQueueConnection();
 102  0
         QueueConnection proxy = (QueueConnection)Proxy.newProxyInstance(Connection.class.getClassLoader(),
 103  
             new Class[]{QueueConnection.class}, new ConnectionInvocationHandler(xaqc));
 104  0
         return proxy;
 105  
     }
 106  
 
 107  
     /*
 108  
      * (non-Javadoc)
 109  
      * 
 110  
      * @see javax.jms.QueueConnectionFactory#createQueueConnection(java.lang.String,
 111  
      *      java.lang.String)
 112  
      */
 113  
     public QueueConnection createQueueConnection(String username, String password) throws JMSException
 114  
     {
 115  0
         XAQueueConnection xaqc = ((XAQueueConnectionFactory)factory).createXAQueueConnection(username,
 116  
             password);
 117  0
         QueueConnection proxy = (QueueConnection)Proxy.newProxyInstance(Connection.class.getClassLoader(),
 118  
             new Class[]{QueueConnection.class}, new ConnectionInvocationHandler(xaqc));
 119  0
         return proxy;
 120  
     }
 121  
 
 122  
     /*
 123  
      * (non-Javadoc)
 124  
      * 
 125  
      * @see javax.jms.TopicConnectionFactory#createTopicConnection()
 126  
      */
 127  
     public TopicConnection createTopicConnection() throws JMSException
 128  
     {
 129  0
         XATopicConnection xatc = ((XATopicConnectionFactory)factory).createXATopicConnection();
 130  0
         TopicConnection proxy = (TopicConnection)Proxy.newProxyInstance(Connection.class.getClassLoader(),
 131  
             new Class[]{TopicConnection.class}, new ConnectionInvocationHandler(xatc));
 132  0
         return proxy;
 133  
     }
 134  
 
 135  
     /*
 136  
      * (non-Javadoc)
 137  
      * 
 138  
      * @see javax.jms.TopicConnectionFactory#createTopicConnection(java.lang.String,
 139  
      *      java.lang.String)
 140  
      */
 141  
     public TopicConnection createTopicConnection(String username, String password) throws JMSException
 142  
     {
 143  0
         XATopicConnection xatc = ((XATopicConnectionFactory)factory).createXATopicConnection(username,
 144  
             password);
 145  0
         TopicConnection proxy = (TopicConnection)Proxy.newProxyInstance(Connection.class.getClassLoader(),
 146  
             new Class[]{TopicConnection.class}, new ConnectionInvocationHandler(xatc));
 147  0
         return proxy;
 148  
     }
 149  
 
 150  0
     public class ConnectionInvocationHandler implements InvocationHandler
 151  
     {
 152  
 
 153  
         private Object xac;
 154  
 
 155  
         public ConnectionInvocationHandler(Object xac)
 156  0
         {
 157  0
             this.xac = xac;
 158  0
         }
 159  
 
 160  
         /**
 161  
          * Can be one of 3 types.
 162  
          * TODO check if we can portably cast it (JMS 1.1 vs 1.0.2b), see Jms102bSupport why
 163  
          * @return underlying XAConnection instance
 164  
          */
 165  
         public Object getTargetObject()
 166  
         {
 167  0
             return xac;
 168  
         }
 169  
 
 170  
         /*
 171  
          * (non-Javadoc)
 172  
          * 
 173  
          * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
 174  
          *      java.lang.reflect.Method, java.lang.Object[])
 175  
          */
 176  
         public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
 177  
         {
 178  0
             if (logger.isDebugEnabled())
 179  
             {
 180  0
                 logger.debug("Invoking " + method);
 181  
             }
 182  0
             if (method.getName().equals("createSession"))
 183  
             {
 184  0
                 XASession xas = ((XAConnection)xac).createXASession();
 185  0
                 return Proxy.newProxyInstance(Session.class.getClassLoader(), new Class[]{Session.class},
 186  
                     new SessionInvocationHandler(xas.getSession(), xas.getXAResource()));
 187  
             }
 188  0
             else if (method.getName().equals("createQueueSession"))
 189  
             {
 190  0
                 XAQueueSession xaqs = ((XAQueueConnection)xac).createXAQueueSession();
 191  0
                 return Proxy.newProxyInstance(Session.class.getClassLoader(),
 192  
                     new Class[]{QueueSession.class}, new SessionInvocationHandler(xaqs.getQueueSession(),
 193  
                         xaqs.getXAResource()));
 194  
             }
 195  0
             else if (method.getName().equals("createTopicSession"))
 196  
             {
 197  0
                 XATopicSession xats = ((XATopicConnection)xac).createXATopicSession();
 198  0
                 return Proxy.newProxyInstance(Session.class.getClassLoader(),
 199  
                     new Class[]{TopicSession.class}, new SessionInvocationHandler(xats.getTopicSession(),
 200  
                         xats.getXAResource()));
 201  
             }
 202  
             else
 203  
             {
 204  0
                 return method.invoke(xac, args);
 205  
             }
 206  
         }
 207  
 
 208  0
         protected class SessionInvocationHandler implements InvocationHandler
 209  
         {
 210  
 
 211  
             private Object session;
 212  
             private Object xares;
 213  
             private Transaction tx;
 214  
 
 215  
             public SessionInvocationHandler(Object session, Object xares)
 216  0
             {
 217  0
                 this.session = session;
 218  0
                 this.xares = xares;
 219  0
             }
 220  
 
 221  
             /*
 222  
              * (non-Javadoc)
 223  
              * 
 224  
              * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
 225  
              *      java.lang.reflect.Method, java.lang.Object[])
 226  
              */
 227  
             public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
 228  
             {
 229  0
                 if (logger.isDebugEnabled())
 230  
                 {
 231  0
                     logger.debug("Invoking " + method);
 232  
                 }
 233  0
                 Object result = method.invoke(session, args);
 234  
 
 235  0
                 if (result instanceof TopicSubscriber)
 236  
                 {
 237  0
                     result = Proxy.newProxyInstance(Session.class.getClassLoader(),
 238  
                         new Class[]{TopicSubscriber.class}, new ConsumerProducerInvocationHandler(result));
 239  
                 }
 240  0
                 else if (result instanceof QueueReceiver)
 241  
                 {
 242  0
                     result = Proxy.newProxyInstance(Session.class.getClassLoader(),
 243  
                         new Class[]{QueueReceiver.class}, new ConsumerProducerInvocationHandler(result));
 244  
                 }
 245  0
                 else if (result instanceof MessageConsumer)
 246  
                 {
 247  0
                     result = Proxy.newProxyInstance(Session.class.getClassLoader(),
 248  
                         new Class[]{MessageConsumer.class}, new ConsumerProducerInvocationHandler(result));
 249  
                 }
 250  0
                 else if (result instanceof TopicPublisher)
 251  
                 {
 252  0
                     result = Proxy.newProxyInstance(Session.class.getClassLoader(),
 253  
                         new Class[]{TopicPublisher.class}, new ConsumerProducerInvocationHandler(result));
 254  
                 }
 255  0
                 else if (result instanceof QueueSender)
 256  
                 {
 257  0
                     result = Proxy.newProxyInstance(Session.class.getClassLoader(),
 258  
                         new Class[]{QueueSender.class}, new ConsumerProducerInvocationHandler(result));
 259  
                 }
 260  0
                 else if (result instanceof MessageProducer)
 261  
                 {
 262  0
                     result = Proxy.newProxyInstance(Session.class.getClassLoader(),
 263  
                         new Class[]{MessageProducer.class}, new ConsumerProducerInvocationHandler(result));
 264  
                 }
 265  0
                 return result;
 266  
             }
 267  
 
 268  
             protected void enlist() throws Exception
 269  
             {
 270  0
                 if (logger.isDebugEnabled())
 271  
                 {
 272  0
                     logger.debug("Enlistment request: " + this);
 273  
                 }
 274  0
                 if (tx == null && tm != null)
 275  
                 {
 276  0
                     tx = tm.getTransaction();
 277  0
                     if (tx != null)
 278  
                     {
 279  0
                         if (logger.isDebugEnabled())
 280  
                         {
 281  0
                             logger.debug("Enlisting resource in xa transaction: " + xares);
 282  
                         }
 283  0
                         XAResource xares = (XAResource)Proxy.newProxyInstance(XAResource.class
 284  
                             .getClassLoader(), new Class[]{XAResource.class},
 285  
                             new XAResourceInvocationHandler());
 286  0
                         tx.enlistResource(xares);
 287  
                     }
 288  
                 }
 289  0
             }
 290  
 
 291  0
             protected class XAResourceInvocationHandler implements InvocationHandler
 292  
             {
 293  
 
 294  
                 /*
 295  
                  * (non-Javadoc)
 296  
                  * 
 297  
                  * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
 298  
                  *      java.lang.reflect.Method, java.lang.Object[])
 299  
                  */
 300  
                 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
 301  
                 {
 302  
                     try
 303  
                     {
 304  0
                         if (logger.isDebugEnabled())
 305  
                         {
 306  0
                             logger.debug("Invoking " + method);
 307  
                         }
 308  0
                         if (method.getName().equals("end"))
 309  
                         {
 310  0
                             tx = null;
 311  
                         }
 312  
 
 313  
                         /*
 314  
                          * This has been added, since JOTM checks if the resource has
 315  
                          * actually been enlisted & tries to compare two proxy
 316  
                          * classes with eachother. Since the equals method is
 317  
                          * proxied, it will effectivly compare a proxy with the
 318  
                          * ConnectionFactory & this will fail. To solve this, if the
 319  
                          * object passed as a parameter is actually another proxy,
 320  
                          * call equals on the proxy passing this class as a
 321  
                          * parameter, effictively we would be comparing the two
 322  
                          * proxied classes.
 323  
                          */
 324  0
                         if (method.getName().equals("equals"))
 325  
                         {
 326  0
                             if (Proxy.isProxyClass(args[0].getClass()))
 327  
                             {
 328  0
                                 return new Boolean(args[0].equals(this));
 329  
                             }
 330  
                             else
 331  
                             {
 332  0
                                 return new Boolean(this.equals(args[0]));
 333  
                             }
 334  
                         }
 335  
 
 336  0
                         return method.invoke(xares, args);
 337  
                     }
 338  0
                     catch (InvocationTargetException e)
 339  
                     {
 340  0
                         throw e.getCause();
 341  
                     }
 342  
                 }
 343  
 
 344  
             }
 345  
 
 346  
             protected class ConsumerProducerInvocationHandler implements InvocationHandler
 347  
             {
 348  
 
 349  
                 private Object target;
 350  
 
 351  
                 public ConsumerProducerInvocationHandler(Object target)
 352  0
                 {
 353  0
                     this.target = target;
 354  0
                 }
 355  
 
 356  
                 /*
 357  
                  * (non-Javadoc)
 358  
                  * 
 359  
                  * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
 360  
                  *      java.lang.reflect.Method, java.lang.Object[])
 361  
                  */
 362  
                 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
 363  
                 {
 364  0
                     if (logger.isDebugEnabled())
 365  
                     {
 366  0
                         logger.debug("Invoking " + method);
 367  
                     }
 368  0
                     if (!method.getName().equals("close"))
 369  
                     {
 370  0
                         enlist();
 371  
                     }
 372  0
                     return method.invoke(target, args);
 373  
                 }
 374  
             }
 375  
 
 376  
         }
 377  
     }
 378  
 
 379  
 }