Coverage Report - org.mule.transport.jms.JmsConnector
 
Classes in this File Line Coverage Branch Coverage Complexity
JmsConnector
0%
0/332
0%
0/118
0
JmsConnector$1
0%
0/4
0%
0/4
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.transport.jms;
 8  
 
 9  
 import org.mule.api.MuleContext;
 10  
 import org.mule.api.MuleException;
 11  
 import org.mule.api.MuleRuntimeException;
 12  
 import org.mule.api.construct.FlowConstruct;
 13  
 import org.mule.api.context.notification.ConnectionNotificationListener;
 14  
 import org.mule.api.endpoint.ImmutableEndpoint;
 15  
 import org.mule.api.endpoint.InboundEndpoint;
 16  
 import org.mule.api.lifecycle.InitialisationException;
 17  
 import org.mule.api.lifecycle.StartException;
 18  
 import org.mule.api.transaction.Transaction;
 19  
 import org.mule.api.transaction.TransactionException;
 20  
 import org.mule.api.transport.ReplyToHandler;
 21  
 import org.mule.config.ExceptionHelper;
 22  
 import org.mule.config.i18n.CoreMessages;
 23  
 import org.mule.config.i18n.MessageFactory;
 24  
 import org.mule.context.notification.ConnectionNotification;
 25  
 import org.mule.context.notification.NotificationException;
 26  
 import org.mule.transaction.TransactionCoordination;
 27  
 import org.mule.transport.AbstractConnector;
 28  
 import org.mule.transport.ConnectException;
 29  
 import org.mule.transport.jms.i18n.JmsMessages;
 30  
 import org.mule.transport.jms.jndi.JndiNameResolver;
 31  
 import org.mule.transport.jms.jndi.SimpleJndiNameResolver;
 32  
 import org.mule.transport.jms.redelivery.AutoDiscoveryRedeliveryHandlerFactory;
 33  
 import org.mule.transport.jms.redelivery.RedeliveryHandlerFactory;
 34  
 import org.mule.transport.jms.xa.ConnectionFactoryWrapper;
 35  
 import org.mule.util.BeanUtils;
 36  
 
 37  
 import java.text.MessageFormat;
 38  
 import java.util.Map;
 39  
 
 40  
 import javax.jms.Connection;
 41  
 import javax.jms.ConnectionFactory;
 42  
 import javax.jms.ExceptionListener;
 43  
 import javax.jms.JMSException;
 44  
 import javax.jms.MessageConsumer;
 45  
 import javax.jms.MessageProducer;
 46  
 import javax.jms.Session;
 47  
 import javax.jms.TemporaryQueue;
 48  
 import javax.jms.TemporaryTopic;
 49  
 import javax.jms.XAConnectionFactory;
 50  
 import javax.naming.CommunicationException;
 51  
 import javax.naming.NamingException;
 52  
 
 53  
 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicInteger;
 54  
 
 55  
 /**
 56  
  * <code>JmsConnector</code> is a JMS 1.0.2b compliant connector that can be used
 57  
  * by a Mule endpoint. The connector supports all JMS functionality including topics
 58  
  * and queues, durable subscribers, acknowledgement modes and local transactions.
 59  
  */
 60  
 
 61  0
 public class JmsConnector extends AbstractConnector implements ExceptionListener
 62  
 {
 63  
 
 64  
     public static final String JMS = "jms";
 65  
 
 66  
     /**
 67  
      * Indicates that Mule should throw an exception on any redelivery attempt.
 68  
      */
 69  
     public static final int REDELIVERY_FAIL_ON_FIRST = 0;
 70  
 
 71  
     public static final int REDELIVERY_IGNORE = -1;
 72  
 
 73  0
     private AtomicInteger receiverReportedExceptionCount = new AtomicInteger();
 74  
 
 75  
     ////////////////////////////////////////////////////////////////////////
 76  
     // Properties
 77  
     ////////////////////////////////////////////////////////////////////////
 78  
 
 79  0
     private int acknowledgementMode = Session.AUTO_ACKNOWLEDGE;
 80  
 
 81  
     private String clientId;
 82  
 
 83  
     private boolean durable;
 84  
 
 85  
     private boolean noLocal;
 86  
 
 87  
     private boolean persistentDelivery;
 88  
 
 89  
     private boolean honorQosHeaders;
 90  
 
 91  0
     private int maxRedelivery = REDELIVERY_FAIL_ON_FIRST;
 92  
 
 93  0
     private boolean cacheJmsSessions = false;
 94  
 
 95  
     /**
 96  
      * Whether to create a consumer on connect.
 97  
      */
 98  0
     private boolean eagerConsumer = true;
 99  
 
 100  
     ////////////////////////////////////////////////////////////////////////
 101  
     // JMS Connection
 102  
     ////////////////////////////////////////////////////////////////////////
 103  
 
 104  
     /**
 105  
      * JMS Connection, not settable by the user.
 106  
      */
 107  
     private Connection connection;
 108  
 
 109  
     private ConnectionFactory connectionFactory;
 110  
 
 111  
     private Map connectionFactoryProperties;
 112  
 
 113  0
     public String username = null;
 114  
 
 115  0
     public String password = null;
 116  
 
 117  
     ////////////////////////////////////////////////////////////////////////
 118  
     // JNDI Connection
 119  
     ////////////////////////////////////////////////////////////////////////
 120  
     private String jndiProviderUrl;
 121  
 
 122  
     private String jndiInitialFactory;
 123  
 
 124  
     private Map jndiProviderProperties;
 125  
 
 126  
     private String connectionFactoryJndiName;
 127  
 
 128  0
     private boolean jndiDestinations = false;
 129  
 
 130  0
     private boolean forceJndiDestinations = false;
 131  
 
 132  
     /**
 133  
      * Resolves JNDI names if the connector uses {@link #jndiDestinations}
 134  
      */
 135  
     private JndiNameResolver jndiNameResolver;
 136  
 
 137  
     ////////////////////////////////////////////////////////////////////////
 138  
     // Strategy classes
 139  
     ////////////////////////////////////////////////////////////////////////
 140  
 
 141  0
     private String specification = JmsConstants.JMS_SPECIFICATION_102B;
 142  
 
 143  
     private JmsSupport jmsSupport;
 144  
 
 145  
     private JmsTopicResolver topicResolver;
 146  
 
 147  
     private RedeliveryHandlerFactory redeliveryHandlerFactory;
 148  
 
 149  
     /**
 150  
      * determines whether a temporary JMSReplyTo destination will be used when using synchronous outbound JMS endpoints
 151  
      */
 152  0
     private boolean disableTemporaryReplyToDestinations = false;
 153  
 
 154  
     /**
 155  
      * If disableTemporaryReplyToDestinations = "true", this flag causes the original JMS Message to be returned as a
 156  
      * synchronous response with any properties set on it by the JMS Provider (e.g., JMSMessageID).
 157  
      *
 158  
      * @see EE-1688/MULE-3059
 159  
      */
 160  0
     private boolean returnOriginalMessageAsReply = false;
 161  
 
 162  
     /**
 163  
      * In-container embedded mode disables some features for strict Java EE compliance.
 164  
      */
 165  
     private boolean embeddedMode;
 166  
 
 167  
     /**
 168  
      * Overrides XaResource.isSameRM() result. Needed for IBM WMQ XA
 169  
      * implementation (set to 'false'). Default value is null (don't override).
 170  
      */
 171  
     private Boolean sameRMOverrideValue;
 172  
 
 173  
     ////////////////////////////////////////////////////////////////////////
 174  
     // Methods
 175  
     ////////////////////////////////////////////////////////////////////////
 176  
 
 177  
     /* Register the Jms Exception reader if this class gets loaded */
 178  
 
 179  
     static
 180  
     {
 181  0
         ExceptionHelper.registerExceptionReader(new JmsExceptionReader());
 182  0
     }
 183  
 
 184  
     public JmsConnector(MuleContext context)
 185  
     {
 186  0
         super(context);
 187  0
     }
 188  
     
 189  
     public String getProtocol()
 190  
     {
 191  0
         return JMS;
 192  
     }
 193  
 
 194  
     @Override
 195  
     protected void doInitialise() throws InitialisationException
 196  
     {        
 197  
         try
 198  
         {
 199  0
             connectionFactory = this.createConnectionFactory();
 200  
         }
 201  0
         catch (NamingException ne)
 202  
         {
 203  0
             throw new InitialisationException(JmsMessages.errorCreatingConnectionFactory(), ne, this);
 204  0
         }
 205  
 
 206  0
         if ((connectionFactoryProperties != null) && !connectionFactoryProperties.isEmpty())
 207  
         {
 208  
             // apply connection factory properties
 209  0
             BeanUtils.populateWithoutFail(connectionFactory, connectionFactoryProperties, true);
 210  
         }
 211  
 
 212  0
         if (topicResolver == null)
 213  
         {
 214  0
             topicResolver = new DefaultJmsTopicResolver(this);
 215  
         }
 216  0
         if (redeliveryHandlerFactory == null)
 217  
         {
 218  0
             redeliveryHandlerFactory = new AutoDiscoveryRedeliveryHandlerFactory(this);
 219  
         }
 220  
 
 221  
         try
 222  
         {
 223  0
             muleContext.registerListener(new ConnectionNotificationListener<ConnectionNotification>()
 224  0
             {
 225  
                 public void onNotification(ConnectionNotification notification)
 226  
                 {
 227  0
                     if (notification.getAction() == ConnectionNotification.CONNECTION_DISCONNECTED
 228  
                             || notification.getAction() == ConnectionNotification.CONNECTION_FAILED)
 229  
                     {
 230  
                         // Remove all dispatchers as any cached session will be invalidated
 231  0
                         clearDispatchers();
 232  
                         // TODO should we dispose receivers here as well (in case they are
 233  
                         // transactional)
 234  
                         // gives a harmless NPE at
 235  
                         // AbstractConnector.connect(AbstractConnector.java:927)
 236  
                         // disposeReceivers();
 237  
                     }
 238  0
                 }
 239  
 
 240  
             }, getName());
 241  
 
 242  
 
 243  
         }
 244  0
         catch (NotificationException nex)
 245  
         {
 246  0
             throw new InitialisationException(nex, this);
 247  0
         }
 248  
 
 249  0
         if (jmsSupport == null)
 250  
         {
 251  0
             jmsSupport = createJmsSupport();
 252  
         }
 253  0
     }
 254  
 
 255  
     /**
 256  
      * A factory method to create various JmsSupport class versions.
 257  
      *
 258  
      * @return JmsSupport instance
 259  
      * @see JmsSupport
 260  
      */
 261  
     protected JmsSupport createJmsSupport()
 262  
     {
 263  
         final JmsSupport result;
 264  0
         if (JmsConstants.JMS_SPECIFICATION_102B.equals(specification))
 265  
         {
 266  0
             result = new Jms102bSupport(this);
 267  
         }
 268  
         else
 269  
         {
 270  0
             result = new Jms11Support(this);
 271  
         }
 272  
 
 273  0
         return result;
 274  
     }
 275  
 
 276  
     protected ConnectionFactory createConnectionFactory() throws InitialisationException, NamingException
 277  
     {
 278  
         // if an initial factory class was configured that takes precedence over the 
 279  
         // spring-configured connection factory or the one that our subclasses may provide
 280  0
         if (jndiInitialFactory != null || jndiNameResolver != null)
 281  
         {
 282  0
             if (jndiNameResolver == null)
 283  
             {
 284  0
                 jndiNameResolver = createDefaultJndiResolver();
 285  
             }
 286  0
             jndiNameResolver.initialise();
 287  
 
 288  0
             Object temp = jndiNameResolver.lookup(connectionFactoryJndiName);
 289  0
             if (temp instanceof ConnectionFactory)
 290  
             {
 291  0
                 return (ConnectionFactory) temp;
 292  
             }
 293  
             else
 294  
             {
 295  0
                 throw new InitialisationException(
 296  
                         JmsMessages.invalidResourceType(ConnectionFactory.class, temp), this);
 297  
             }
 298  
         }
 299  
         else
 300  
         {
 301  
             // don't look up objects from JNDI in any case
 302  0
             jndiDestinations = false;
 303  0
             forceJndiDestinations = false;
 304  
 
 305  
             // don't use JNDI. Use the spring-configured connection factory if that's provided
 306  0
             if (connectionFactory != null)
 307  
             {
 308  0
                 return connectionFactory;
 309  
             }
 310  
 
 311  
             // no spring-configured connection factory. See if there is a default one (e.g. from
 312  
             // subclass)
 313  
             ConnectionFactory factory;
 314  
             try
 315  
             {
 316  0
                 factory = getDefaultConnectionFactory();
 317  
             }
 318  0
             catch (Exception e)
 319  
             {
 320  0
                 throw new InitialisationException(e, this);
 321  0
             }
 322  0
             if (factory == null)
 323  
             {
 324  
                 // no connection factory ... give up
 325  0
                 throw new InitialisationException(JmsMessages.noConnectionFactoryConfigured(), this);
 326  
             }
 327  0
             return factory;
 328  
         }
 329  
     }
 330  
 
 331  
     private JndiNameResolver createDefaultJndiResolver()
 332  
     {
 333  0
         if (logger.isDebugEnabled())
 334  
         {
 335  0
             logger.debug("Creating default JndiNameResolver");
 336  
         }
 337  
 
 338  0
         SimpleJndiNameResolver jndiContextFactory = new SimpleJndiNameResolver();
 339  0
         jndiContextFactory.setJndiProviderUrl(jndiProviderUrl);
 340  0
         jndiContextFactory.setJndiInitialFactory(jndiInitialFactory);
 341  0
         jndiContextFactory.setJndiProviderProperties(jndiProviderProperties);
 342  
 
 343  0
         return jndiContextFactory;
 344  
     }
 345  
 
 346  
     /**
 347  
      * Override this method to provide a default ConnectionFactory for a vendor-specific JMS Connector.
 348  
      * @throws Exception
 349  
      */
 350  
     protected ConnectionFactory getDefaultConnectionFactory() throws Exception
 351  
     {
 352  0
         return null;
 353  
     }
 354  
 
 355  
     @Override
 356  
     protected void doDispose()
 357  
     {
 358  0
         if (connection != null)
 359  
         {
 360  
             try
 361  
             {
 362  0
                 connection.close();
 363  
             }
 364  0
             catch (JMSException e)
 365  
             {
 366  0
                 logger.error("Jms connector failed to dispose properly: ", e);
 367  0
             }
 368  0
             connection = null;
 369  
         }
 370  
 
 371  0
         if (jndiNameResolver != null)
 372  
         {
 373  0
             jndiNameResolver.dispose();
 374  
         }
 375  0
     }
 376  
 
 377  
     protected Object lookupFromJndi(String jndiName) throws NamingException
 378  
     {
 379  
         try
 380  
         {
 381  0
             return jndiNameResolver.lookup(jndiName);
 382  
         }
 383  0
         catch (CommunicationException ce)
 384  
         {
 385  
             try
 386  
             {
 387  0
                 final Transaction tx = TransactionCoordination.getInstance().getTransaction();
 388  0
                 if (tx != null)
 389  
                 {
 390  0
                     tx.setRollbackOnly();
 391  
                 }
 392  
             }
 393  0
             catch (TransactionException e)
 394  
             {
 395  0
                 throw new MuleRuntimeException(
 396  
                         MessageFactory.createStaticMessage("Failed to mark transaction for rollback: "), e);
 397  0
             }
 398  
 
 399  
             // re-throw
 400  0
             throw ce;
 401  
         }
 402  
     }
 403  
 
 404  
     protected Connection createConnection() throws NamingException, JMSException, InitialisationException
 405  
     {
 406  0
         ConnectionFactory cf = this.connectionFactory;
 407  
         Connection connection;
 408  
 
 409  
         try
 410  
         {
 411  0
             if (cf instanceof XAConnectionFactory && muleContext.getTransactionManager() != null)
 412  
             {
 413  0
                 cf = new ConnectionFactoryWrapper(cf, sameRMOverrideValue);
 414  
             }
 415  
         }
 416  0
         catch (Exception e)
 417  
         {
 418  0
             throw new InitialisationException(e, this);
 419  0
         }
 420  
 
 421  0
         if (username != null)
 422  
         {
 423  0
             connection = jmsSupport.createConnection(cf, username, password);
 424  
         }
 425  
         else
 426  
         {
 427  0
             connection = jmsSupport.createConnection(cf);
 428  
         }
 429  
 
 430  0
         if (connection != null)
 431  
         {
 432  
             // EE-1901: only sets the clientID if it was not already set
 433  0
             if (clientId != null && !clientId.equals(connection.getClientID()))
 434  
             {
 435  0
                 connection.setClientID(getClientId());
 436  
             }
 437  0
             if (!embeddedMode)
 438  
             {
 439  0
                 connection.setExceptionListener(this);
 440  
             }
 441  
         }
 442  
 
 443  
 
 444  0
         return connection;
 445  
     }
 446  
 
 447  
     public void onException(JMSException jmsException)
 448  
     {
 449  0
         final JmsConnector jmsConnector = JmsConnector.this;
 450  0
         Map receivers = jmsConnector.getReceivers();
 451  0
         boolean isMultiConsumerReceiver = false;
 452  
 
 453  0
         if (!receivers.isEmpty())
 454  
         {
 455  0
             Map.Entry entry = (Map.Entry) receivers.entrySet().iterator().next();
 456  0
             if (entry.getValue() instanceof MultiConsumerJmsMessageReceiver)
 457  
             {
 458  0
                 isMultiConsumerReceiver = true;
 459  
             }
 460  
         }
 461  
 
 462  0
         int expectedReceiverCount = isMultiConsumerReceiver ? 1 :
 463  
                 (jmsConnector.getReceivers().size() * jmsConnector.getNumberOfConcurrentTransactedReceivers());
 464  
 
 465  0
         if (logger.isDebugEnabled())
 466  
         {
 467  0
             logger.debug("About to recycle myself due to remote JMS connection shutdown but need "
 468  
                     + "to wait for all active receivers to report connection loss. Receiver count: "
 469  
                     + (receiverReportedExceptionCount.get() + 1) + '/' + expectedReceiverCount);
 470  
         }
 471  
 
 472  0
         if (receiverReportedExceptionCount.incrementAndGet() >= expectedReceiverCount)
 473  
         {
 474  0
             receiverReportedExceptionCount.set(0);
 475  
 
 476  0
             handleException(new ConnectException(jmsException, this));
 477  
         }
 478  0
     }
 479  
 
 480  
     @Override
 481  
     protected void doConnect() throws Exception
 482  
     {
 483  0
         connection = createConnection();
 484  0
         if (isStarted())
 485  
         {
 486  0
             connection.start();
 487  
         }
 488  0
     }
 489  
 
 490  
     @Override
 491  
     protected void doDisconnect() throws Exception
 492  
     {
 493  
         try
 494  
         {
 495  0
             if (connection != null)
 496  
             {
 497  
                 // Ignore exceptions while closing the connection
 498  0
                 if (!embeddedMode)
 499  
                 {
 500  0
                     connection.setExceptionListener(null);
 501  
                 }
 502  0
                 connection.close();
 503  
             }
 504  
         }
 505  
         finally
 506  
         {
 507  0
             connection = null;
 508  0
         }
 509  0
     }
 510  
 
 511  
     @Override
 512  
     protected Object getReceiverKey(FlowConstruct flowConstruct, InboundEndpoint endpoint)
 513  
     {
 514  0
         return flowConstruct.getName() + "~" + endpoint.getEndpointURI().getAddress();
 515  
     }
 516  
 
 517  
     public Session getSessionFromTransaction()
 518  
     {
 519  0
         Transaction tx = TransactionCoordination.getInstance().getTransaction();
 520  0
         if (tx != null)
 521  
         {
 522  0
             if (tx.hasResource(connection))
 523  
             {
 524  0
                 if (logger.isDebugEnabled())
 525  
                 {
 526  0
                     logger.debug("Retrieving jms session from current transaction " + tx);
 527  
                 }
 528  
 
 529  0
                 Session session = (Session) tx.getResource(connection);
 530  
 
 531  0
                 if (logger.isDebugEnabled())
 532  
                 {
 533  0
                     logger.debug("Using " + session + " bound to transaction " + tx);
 534  
                 }
 535  
 
 536  0
                 return session;
 537  
             }
 538  
         }
 539  0
         return null;
 540  
     }
 541  
 
 542  
     public Session getSession(ImmutableEndpoint endpoint) throws JMSException
 543  
     {
 544  0
         final boolean topic = getTopicResolver().isTopic(endpoint);
 545  0
         return getSession(endpoint.getTransactionConfig().isTransacted(), topic);
 546  
     }
 547  
 
 548  
     public Session getSession(boolean transacted, boolean topic) throws JMSException
 549  
     {
 550  0
         Session session = getSessionFromTransaction();
 551  0
         if (session != null)
 552  
         {
 553  0
             return session;
 554  
         }
 555  
 
 556  0
         Transaction tx = TransactionCoordination.getInstance().getTransaction();
 557  
 
 558  0
         session = jmsSupport.createSession(connection, topic, transacted, acknowledgementMode, noLocal);
 559  
 
 560  0
         if (logger.isDebugEnabled())
 561  
         {
 562  0
             logger.debug(MessageFormat.format(
 563  
                     "Retrieved new jms session from connection: " +
 564  
                             "topic={0}, transacted={1}, ack mode={2}, nolocal={3}: {4}",
 565  
                     topic, transacted, acknowledgementMode, noLocal, session));
 566  
         }
 567  
 
 568  0
         if (tx != null)
 569  
         {
 570  0
             logger.debug("Binding session " + session + " to current transaction " + tx);
 571  
             try
 572  
             {
 573  0
                 tx.bindResource(connection, session);
 574  
             }
 575  0
             catch (TransactionException e)
 576  
             {
 577  0
                 closeQuietly(session);
 578  0
                 throw new RuntimeException("Could not bind session to current transaction", e);
 579  0
             }
 580  
         }
 581  0
         return session;
 582  
     }
 583  
 
 584  
     @Override
 585  
     protected void doStart() throws MuleException
 586  
     {
 587  
         //TODO: This should never be null or an exception should be thrown
 588  0
         if (connection != null)
 589  
         {
 590  
             try
 591  
             {
 592  0
                 connection.start();
 593  
             }
 594  0
             catch (JMSException e)
 595  
             {
 596  0
                 throw new StartException(CoreMessages.failedToStart("Jms Connection"), e, this);
 597  0
             }
 598  
         }
 599  
 
 600  0
         if (jndiNameResolver != null)
 601  
         {
 602  0
             jndiNameResolver.start();
 603  
         }
 604  0
     }
 605  
 
 606  
 
 607  
     /**
 608  
      * Closes a session if there is no active transaction in the current thread, otherwise the
 609  
      * session will continue active until there is a direct call to close it.
 610  
      *
 611  
      * @param session the session that ill be closed if there is an active transaction.
 612  
      */
 613  
     public void closeSessionIfNoTransactionActive(Session session)
 614  
     {
 615  0
         final Transaction transaction = TransactionCoordination.getInstance().getTransaction();
 616  0
         if (transaction == null)
 617  
         {
 618  0
             if (logger.isDebugEnabled())
 619  
             {
 620  0
                 logger.error("Closing non-TX session: " + session);
 621  
             }
 622  0
             closeQuietly(session);
 623  
         }
 624  0
         else if (logger.isDebugEnabled())
 625  
         {
 626  0
             logger.error("Not closing TX session: " + session);
 627  
         }
 628  0
     }
 629  
 
 630  
     @Override
 631  
     protected void doStop() throws MuleException
 632  
     {
 633  0
         if (connection != null)
 634  
         {
 635  
             try
 636  
             {
 637  0
                 connection.stop();
 638  
             }
 639  0
             catch (Exception e)
 640  
             {
 641  
                 // this exception may be thrown when the broker is shut down, but the
 642  
                 // stop process should continue all the same
 643  0
                 logger.warn("Jms connection failed to stop properly: ", e);
 644  0
             }
 645  
         }
 646  
 
 647  0
         if (jndiNameResolver != null)
 648  
         {
 649  0
             jndiNameResolver.stop();
 650  
         }
 651  0
     }
 652  
 
 653  
     @Override
 654  
     public ReplyToHandler getReplyToHandler(ImmutableEndpoint endpoint)
 655  
     {
 656  0
         return new JmsReplyToHandler(this, getDefaultResponseTransformers(endpoint));
 657  
     }
 658  
 
 659  
     /**
 660  
      * This method may be overridden in case a certain JMS implementation does not
 661  
      * support all the standard JMS properties.
 662  
      */
 663  
     public boolean supportsProperty(String property)
 664  
     {
 665  0
         return true;
 666  
     }
 667  
 
 668  
     /**
 669  
      * This method may be overridden in order to apply pre-processing to the message
 670  
      * as soon as it arrives.
 671  
      *
 672  
      * @param message - the incoming message
 673  
      * @param session - the JMS session
 674  
      * @return the preprocessed message
 675  
      */
 676  
     public javax.jms.Message preProcessMessage(javax.jms.Message message, Session session) throws Exception
 677  
     {
 678  0
         return message;
 679  
     }
 680  
 
 681  
     /**
 682  
      * Closes the MessageProducer
 683  
      *
 684  
      * @param producer
 685  
      * @throws JMSException
 686  
      */
 687  
     public void close(MessageProducer producer) throws JMSException
 688  
     {
 689  0
         if (producer != null)
 690  
         {
 691  0
             if (logger.isDebugEnabled())
 692  
             {
 693  0
                 logger.debug("Closing producer: " + producer);
 694  
             }
 695  0
             producer.close();
 696  
         }
 697  0
         else if (logger.isDebugEnabled())
 698  
         {
 699  0
             logger.debug("Producer is null, nothing to close");
 700  
         }
 701  0
     }
 702  
 
 703  
     /**
 704  
      * Closes the MessageProducer without throwing an exception (an error message is
 705  
      * logged instead).
 706  
      *
 707  
      * @param producer
 708  
      */
 709  
     public void closeQuietly(MessageProducer producer)
 710  
     {
 711  
         try
 712  
         {
 713  0
             close(producer);
 714  
         }
 715  0
         catch (Exception e)
 716  
         {
 717  0
             logger.warn("Failed to close jms message producer: " + e.getMessage());
 718  0
         }
 719  0
     }
 720  
 
 721  
     /**
 722  
      * Closes the MessageConsumer
 723  
      *
 724  
      * @param consumer
 725  
      * @throws JMSException
 726  
      */
 727  
     public void close(MessageConsumer consumer) throws JMSException
 728  
     {
 729  0
         if (consumer != null)
 730  
         {
 731  0
             if (logger.isDebugEnabled())
 732  
             {
 733  0
                 logger.debug("Closing consumer: " + consumer);
 734  
             }
 735  0
             consumer.close();
 736  
         }
 737  0
         else if (logger.isDebugEnabled())
 738  
         {
 739  0
             logger.debug("Consumer is null, nothing to close");
 740  
         }
 741  0
     }
 742  
 
 743  
     /**
 744  
      * Closes the MessageConsumer without throwing an exception (an error message is
 745  
      * logged instead).
 746  
      *
 747  
      * @param consumer
 748  
      */
 749  
     public void closeQuietly(MessageConsumer consumer)
 750  
     {
 751  
         try
 752  
         {
 753  0
             close(consumer);
 754  
         }
 755  0
         catch (Exception e)
 756  
         {
 757  0
             logger.warn("Failed to close jms message consumer: " + e.getMessage());
 758  0
         }
 759  0
     }
 760  
 
 761  
     /**
 762  
      * Closes the MuleSession
 763  
      *
 764  
      * @param session
 765  
      * @throws JMSException
 766  
      */
 767  
     public void close(Session session) throws JMSException
 768  
     {
 769  0
         if (session != null)
 770  
         {
 771  0
             if (logger.isDebugEnabled())
 772  
             {
 773  0
                 logger.debug("Closing session " + session);
 774  
             }
 775  0
             session.close();
 776  
         }
 777  0
     }
 778  
 
 779  
     /**
 780  
      * Closes the MuleSession without throwing an exception (an error message is logged
 781  
      * instead).
 782  
      *
 783  
      * @param session
 784  
      */
 785  
     public void closeQuietly(Session session)
 786  
     {
 787  
         try
 788  
         {
 789  0
             close(session);
 790  
         }
 791  0
         catch (Exception e)
 792  
         {
 793  0
             logger.warn("Failed to close jms session consumer: " + e.getMessage());
 794  0
         }
 795  0
     }
 796  
 
 797  
     /**
 798  
      * Closes the TemporaryQueue
 799  
      *
 800  
      * @param tempQueue
 801  
      * @throws JMSException
 802  
      */
 803  
     public void close(TemporaryQueue tempQueue) throws JMSException
 804  
     {
 805  0
         if (tempQueue != null)
 806  
         {
 807  0
             tempQueue.delete();
 808  
         }
 809  0
     }
 810  
 
 811  
     /**
 812  
      * Closes the TemporaryQueue without throwing an exception (an error message is
 813  
      * logged instead).
 814  
      *
 815  
      * @param tempQueue
 816  
      */
 817  
     public void closeQuietly(TemporaryQueue tempQueue)
 818  
     {
 819  
         try
 820  
         {
 821  0
             close(tempQueue);
 822  
         }
 823  0
         catch (Exception e)
 824  
         {
 825  0
             if (logger.isWarnEnabled())
 826  
             {
 827  0
                 String queueName = "";
 828  
                 try
 829  
                 {
 830  0
                     queueName = tempQueue.getQueueName();
 831  
                 }
 832  0
                 catch (JMSException innerEx)
 833  
                 {
 834  
                     // ignore, we are just trying to get the queue name
 835  0
                 }
 836  0
                 logger.warn(MessageFormat.format(
 837  
                         "Failed to delete a temporary queue ''{0}'' Reason: {1}",
 838  
                         queueName, e.getMessage()));
 839  
             }
 840  0
         }
 841  0
     }
 842  
 
 843  
     /**
 844  
      * Closes the TemporaryTopic
 845  
      *
 846  
      * @param tempTopic
 847  
      * @throws JMSException
 848  
      */
 849  
     public void close(TemporaryTopic tempTopic) throws JMSException
 850  
     {
 851  0
         if (tempTopic != null)
 852  
         {
 853  0
             tempTopic.delete();
 854  
         }
 855  0
     }
 856  
 
 857  
     /**
 858  
      * Closes the TemporaryTopic without throwing an exception (an error message is
 859  
      * logged instead).
 860  
      *
 861  
      * @param tempTopic
 862  
      */
 863  
     public void closeQuietly(TemporaryTopic tempTopic)
 864  
     {
 865  
         try
 866  
         {
 867  0
             close(tempTopic);
 868  
         }
 869  0
         catch (Exception e)
 870  
         {
 871  0
             if (logger.isWarnEnabled())
 872  
             {
 873  0
                 String topicName = "";
 874  
                 try
 875  
                 {
 876  0
                     topicName = tempTopic.getTopicName();
 877  
                 }
 878  0
                 catch (JMSException innerEx)
 879  
                 {
 880  
                     // ignore, we are just trying to get the topic name
 881  0
                 }
 882  0
                 logger.warn("Failed to delete a temporary topic " + topicName + ": " + e.getMessage());
 883  
             }
 884  0
         }
 885  0
     }
 886  
 
 887  
     ////////////////////////////////////////////////////////////////////////
 888  
     // Getters and Setters
 889  
     ////////////////////////////////////////////////////////////////////////
 890  
 
 891  
     /**
 892  
      * @return Returns the connection.
 893  
      */
 894  
     public Connection getConnection()
 895  
     {
 896  0
         return connection;
 897  
     }
 898  
 
 899  
     protected void setConnection(Connection connection)
 900  
     {
 901  0
         this.connection = connection;
 902  0
     }
 903  
 
 904  
     /**
 905  
      * @return Returns the acknowledgeMode.
 906  
      */
 907  
     public int getAcknowledgementMode()
 908  
     {
 909  0
         return acknowledgementMode;
 910  
     }
 911  
 
 912  
     /**
 913  
      * @param acknowledgementMode The acknowledgementMode to set.
 914  
      */
 915  
     public void setAcknowledgementMode(int acknowledgementMode)
 916  
     {
 917  0
         this.acknowledgementMode = acknowledgementMode;
 918  0
     }
 919  
 
 920  
     /**
 921  
      * @return Returns the durable.
 922  
      */
 923  
     public boolean isDurable()
 924  
     {
 925  0
         return durable;
 926  
     }
 927  
 
 928  
     /**
 929  
      * @param durable The durable to set.
 930  
      */
 931  
     public void setDurable(boolean durable)
 932  
     {
 933  0
         this.durable = durable;
 934  0
     }
 935  
 
 936  
     /**
 937  
      * @return Returns the noLocal.
 938  
      */
 939  
     public boolean isNoLocal()
 940  
     {
 941  0
         return noLocal;
 942  
     }
 943  
 
 944  
     /**
 945  
      * @param noLocal The noLocal to set.
 946  
      */
 947  
     public void setNoLocal(boolean noLocal)
 948  
     {
 949  0
         this.noLocal = noLocal;
 950  0
     }
 951  
 
 952  
     /**
 953  
      * @return Returns the persistentDelivery.
 954  
      */
 955  
     public boolean isPersistentDelivery()
 956  
     {
 957  0
         return persistentDelivery;
 958  
     }
 959  
 
 960  
     /**
 961  
      * @param persistentDelivery The persistentDelivery to set.
 962  
      */
 963  
     public void setPersistentDelivery(boolean persistentDelivery)
 964  
     {
 965  0
         this.persistentDelivery = persistentDelivery;
 966  0
     }
 967  
 
 968  
     public JmsSupport getJmsSupport()
 969  
     {
 970  0
         return jmsSupport;
 971  
     }
 972  
 
 973  
     public void setJmsSupport(JmsSupport jmsSupport)
 974  
     {
 975  0
         this.jmsSupport = jmsSupport;
 976  0
     }
 977  
 
 978  
     public String getSpecification()
 979  
     {
 980  0
         return specification;
 981  
     }
 982  
 
 983  
     public void setSpecification(String specification)
 984  
     {
 985  0
         if (JmsConstants.JMS_SPECIFICATION_11.equals(specification)
 986  
             || (JmsConstants.JMS_SPECIFICATION_102B.equals(specification)))
 987  
         {
 988  0
             this.specification = specification;
 989  
         }
 990  
         else
 991  
         {
 992  0
             throw new IllegalArgumentException(
 993  
                 "JMS specification needs to be one of the defined values in JmsConstants but was: "
 994  
                                 + specification);
 995  
         }
 996  0
     }
 997  
 
 998  
     public String getUsername()
 999  
     {
 1000  0
         return username;
 1001  
     }
 1002  
 
 1003  
     public void setUsername(String username)
 1004  
     {
 1005  0
         this.username = username;
 1006  0
     }
 1007  
 
 1008  
     public String getPassword()
 1009  
     {
 1010  0
         return password;
 1011  
     }
 1012  
 
 1013  
     public void setPassword(String password)
 1014  
     {
 1015  0
         this.password = password;
 1016  0
     }
 1017  
 
 1018  
     public String getClientId()
 1019  
     {
 1020  0
         return clientId;
 1021  
     }
 1022  
 
 1023  
     public void setClientId(String clientId)
 1024  
     {
 1025  0
         this.clientId = clientId;
 1026  0
     }
 1027  
 
 1028  
     public int getMaxRedelivery()
 1029  
     {
 1030  0
         return maxRedelivery;
 1031  
     }
 1032  
 
 1033  
     public void setMaxRedelivery(int maxRedelivery)
 1034  
     {
 1035  0
         this.maxRedelivery = maxRedelivery;
 1036  0
     }
 1037  
 
 1038  
     @Override
 1039  
     public boolean isResponseEnabled()
 1040  
     {
 1041  0
         return true;
 1042  
     }
 1043  
 
 1044  
 
 1045  
     /**
 1046  
      * Getter for property 'topicResolver'.
 1047  
      *
 1048  
      * @return Value for property 'topicResolver'.
 1049  
      */
 1050  
     public JmsTopicResolver getTopicResolver()
 1051  
     {
 1052  0
         return topicResolver;
 1053  
     }
 1054  
 
 1055  
     /**
 1056  
      * Setter for property 'topicResolver'.
 1057  
      *
 1058  
      * @param topicResolver Value to set for property 'topicResolver'.
 1059  
      */
 1060  
     public void setTopicResolver(final JmsTopicResolver topicResolver)
 1061  
     {
 1062  0
         this.topicResolver = topicResolver;
 1063  0
     }
 1064  
 
 1065  
     /**
 1066  
      * Getter for property 'eagerConsumer'. Default
 1067  
      * is {@code true}.
 1068  
      *
 1069  
      * @return Value for property 'eagerConsumer'.
 1070  
      * @see #eagerConsumer
 1071  
      */
 1072  
     public boolean isEagerConsumer()
 1073  
     {
 1074  0
         return eagerConsumer;
 1075  
     }
 1076  
 
 1077  
     /**
 1078  
      * A value of {@code true} will create a consumer on
 1079  
      * connect, in contrast to lazy instantiation in the poll loop.
 1080  
      * This setting very much depends on the JMS vendor.
 1081  
      * Affects transactional receivers, typical symptoms are:
 1082  
      * <ul>
 1083  
      * <li> consumer thread hanging forever, though a message is
 1084  
      * available
 1085  
      * <li>failure to consume the first message (the rest
 1086  
      * are fine)
 1087  
      * </ul>
 1088  
      * <p/>
 1089  
      *
 1090  
      * @param eagerConsumer Value to set for property 'eagerConsumer'.
 1091  
      * @see #eagerConsumer
 1092  
      * @see org.mule.transport.jms.XaTransactedJmsMessageReceiver
 1093  
      */
 1094  
     public void setEagerConsumer(final boolean eagerConsumer)
 1095  
     {
 1096  0
         this.eagerConsumer = eagerConsumer;
 1097  0
     }
 1098  
 
 1099  
     public boolean isCacheJmsSessions()
 1100  
     {
 1101  0
         return cacheJmsSessions;
 1102  
     }
 1103  
 
 1104  
     public void setCacheJmsSessions(boolean cacheJmsSessions)
 1105  
     {
 1106  0
         this.cacheJmsSessions = cacheJmsSessions;
 1107  0
     }
 1108  
 
 1109  
     public ConnectionFactory getConnectionFactory()
 1110  
     {
 1111  0
         return connectionFactory;
 1112  
     }
 1113  
 
 1114  
     public void setConnectionFactory(ConnectionFactory connectionFactory)
 1115  
     {
 1116  0
         this.connectionFactory = connectionFactory;
 1117  0
     }
 1118  
 
 1119  
     public RedeliveryHandlerFactory getRedeliveryHandlerFactory()
 1120  
     {
 1121  0
         return redeliveryHandlerFactory;
 1122  
     }
 1123  
 
 1124  
     public void setRedeliveryHandlerFactory(RedeliveryHandlerFactory redeliveryHandlerFactory)
 1125  
     {
 1126  0
         this.redeliveryHandlerFactory = redeliveryHandlerFactory;
 1127  0
     }
 1128  
 
 1129  
     /**
 1130  
      * Sets the <code>honorQosHeaders</code> property, which determines whether
 1131  
      * {@link JmsMessageDispatcher} should honor incoming message's QoS headers
 1132  
      * (JMSPriority, JMSDeliveryMode).
 1133  
      *
 1134  
      * @param honorQosHeaders <code>true</code> if {@link JmsMessageDispatcher}
 1135  
      *                        should honor incoming message's QoS headers; otherwise
 1136  
      *                        <code>false</code> Default is <code>false</code>, meaning that
 1137  
      *                        connector settings will override message headers.
 1138  
      */
 1139  
     public void setHonorQosHeaders(boolean honorQosHeaders)
 1140  
     {
 1141  0
         this.honorQosHeaders = honorQosHeaders;
 1142  0
     }
 1143  
 
 1144  
     /**
 1145  
      * Gets the value of <code>honorQosHeaders</code> property.
 1146  
      *
 1147  
      * @return <code>true</code> if <code>JmsMessageDispatcher</code> should
 1148  
      *         honor incoming message's QoS headers; otherwise <code>false</code>
 1149  
      *         Default is <code>false</code>, meaning that connector settings will
 1150  
      *         override message headers.
 1151  
      */
 1152  
     public boolean isHonorQosHeaders()
 1153  
     {
 1154  0
         return honorQosHeaders;
 1155  
     }
 1156  
 
 1157  
     /**
 1158  
      * @Deprecated use a {@link JndiNameResolver} instead of access this property
 1159  
      */
 1160  
     @Deprecated
 1161  
     public String getJndiInitialFactory()
 1162  
     {
 1163  0
         return jndiInitialFactory;
 1164  
     }
 1165  
 
 1166  
     /**
 1167  
      * @Deprecated use a {@link JndiNameResolver} instead of access this property
 1168  
      */
 1169  
     @Deprecated
 1170  
     public void setJndiInitialFactory(String jndiInitialFactory)
 1171  
     {
 1172  0
         this.jndiInitialFactory = jndiInitialFactory;
 1173  0
     }
 1174  
 
 1175  
     /**
 1176  
      * @Deprecated use a {@link JndiNameResolver} instead of access this property
 1177  
      */
 1178  
     @Deprecated
 1179  
     public String getJndiProviderUrl()
 1180  
     {
 1181  0
         return jndiProviderUrl;
 1182  
     }
 1183  
 
 1184  
     /**
 1185  
      * @Deprecated use a {@link JndiNameResolver} instead of access this property
 1186  
      */
 1187  
     @Deprecated
 1188  
     public void setJndiProviderUrl(String jndiProviderUrl)
 1189  
     {
 1190  0
         this.jndiProviderUrl = jndiProviderUrl;
 1191  0
     }
 1192  
 
 1193  
     /**
 1194  
      * @Deprecated use a {@link JndiNameResolver} instead of access this property
 1195  
      */
 1196  
     @Deprecated
 1197  
     public Map getJndiProviderProperties()
 1198  
     {
 1199  0
         return jndiProviderProperties;
 1200  
     }
 1201  
 
 1202  
     /**
 1203  
      * @Deprecated use a {@link JndiNameResolver} instead of access this property
 1204  
      */
 1205  
     @Deprecated
 1206  
     public void setJndiProviderProperties(Map jndiProviderProperties)
 1207  
     {
 1208  0
         this.jndiProviderProperties = jndiProviderProperties;
 1209  0
     }
 1210  
 
 1211  
     public JndiNameResolver getJndiNameResolver()
 1212  
     {
 1213  0
         return jndiNameResolver;
 1214  
     }
 1215  
 
 1216  
     public void setJndiNameResolver(JndiNameResolver jndiNameResolver)
 1217  
     {
 1218  0
         this.jndiNameResolver = jndiNameResolver;
 1219  0
     }
 1220  
 
 1221  
     public String getConnectionFactoryJndiName()
 1222  
     {
 1223  0
         return connectionFactoryJndiName;
 1224  
     }
 1225  
 
 1226  
     public void setConnectionFactoryJndiName(String connectionFactoryJndiName)
 1227  
     {
 1228  0
         this.connectionFactoryJndiName = connectionFactoryJndiName;
 1229  0
     }
 1230  
 
 1231  
     public boolean isJndiDestinations()
 1232  
     {
 1233  0
         return jndiDestinations;
 1234  
     }
 1235  
 
 1236  
     public void setJndiDestinations(boolean jndiDestinations)
 1237  
     {
 1238  0
         this.jndiDestinations = jndiDestinations;
 1239  0
     }
 1240  
 
 1241  
     public boolean isForceJndiDestinations()
 1242  
     {
 1243  0
         return forceJndiDestinations;
 1244  
     }
 1245  
 
 1246  
     public void setForceJndiDestinations(boolean forceJndiDestinations)
 1247  
     {
 1248  0
         this.forceJndiDestinations = forceJndiDestinations;
 1249  0
     }
 1250  
 
 1251  
     public boolean isDisableTemporaryReplyToDestinations()
 1252  
     {
 1253  0
         return disableTemporaryReplyToDestinations;
 1254  
     }
 1255  
 
 1256  
     public void setDisableTemporaryReplyToDestinations(boolean disableTemporaryReplyToDestinations)
 1257  
     {
 1258  0
         this.disableTemporaryReplyToDestinations = disableTemporaryReplyToDestinations;
 1259  0
     }
 1260  
 
 1261  
     public boolean isReturnOriginalMessageAsReply()
 1262  
     {
 1263  0
         return returnOriginalMessageAsReply;
 1264  
     }
 1265  
 
 1266  
     public void setReturnOriginalMessageAsReply(boolean returnOriginalMessageAsReply)
 1267  
     {
 1268  0
         this.returnOriginalMessageAsReply = returnOriginalMessageAsReply;
 1269  0
     }
 1270  
 
 1271  
     /**
 1272  
      * @return Returns underlying connection factory properties.
 1273  
      */
 1274  
     public Map getConnectionFactoryProperties()
 1275  
     {
 1276  0
         return connectionFactoryProperties;
 1277  
     }
 1278  
 
 1279  
     /**
 1280  
      * @param connectionFactoryProperties properties to be set on the underlying
 1281  
      *                                    ConnectionFactory.
 1282  
      */
 1283  
     public void setConnectionFactoryProperties(Map connectionFactoryProperties)
 1284  
     {
 1285  0
         this.connectionFactoryProperties = connectionFactoryProperties;
 1286  0
     }
 1287  
 
 1288  
     /**
 1289  
      * A synonym for {@link #numberOfConcurrentTransactedReceivers}. Note that
 1290  
      * it affects both transactional and non-transactional scenarios.
 1291  
      *
 1292  
      * @param count number of consumers
 1293  
      */
 1294  
     public void setNumberOfConsumers(int count)
 1295  
     {
 1296  0
         this.numberOfConcurrentTransactedReceivers = count;
 1297  0
     }
 1298  
 
 1299  
     /**
 1300  
      * A synonym for {@link #numberOfConcurrentTransactedReceivers}.
 1301  
      *
 1302  
      * @return number of consumers
 1303  
      */
 1304  
     public int getNumberOfConsumers()
 1305  
     {
 1306  0
         return this.numberOfConcurrentTransactedReceivers;
 1307  
     }
 1308  
 
 1309  
     public boolean isEmbeddedMode()
 1310  
     {
 1311  0
         return embeddedMode;
 1312  
     }
 1313  
 
 1314  
     public void setEmbeddedMode(boolean embeddedMode)
 1315  
     {
 1316  0
         this.embeddedMode = embeddedMode;
 1317  0
     }
 1318  
 
 1319  
     public Boolean getSameRMOverrideValue()
 1320  
     {
 1321  0
         return sameRMOverrideValue;
 1322  
     }
 1323  
 
 1324  
     public void setSameRMOverrideValue(Boolean sameRMOverrideValue)
 1325  
     {
 1326  0
         this.sameRMOverrideValue = sameRMOverrideValue;
 1327  0
     }
 1328  
 }