Coverage Report - org.mule.transport.jms.mulemq.MuleMQJmsConnector
 
Classes in this File Line Coverage Branch Coverage Complexity
MuleMQJmsConnector
0%
0/152
0%
0/30
0
 
 1  
 /*
 2  
  * $Id: MuleMQJmsConnector.java 19191 2010-08-25 21:05:23Z tcarlson $
 3  
  * --------------------------------------------------------------------------------------
 4  
  * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.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.transport.jms.mulemq;
 12  
 
 13  
 import org.mule.api.MuleContext;
 14  
 import org.mule.api.lifecycle.InitialisationException;
 15  
 import org.mule.config.ExceptionHelper;
 16  
 import org.mule.transport.jms.JmsConnector;
 17  
 import org.mule.transport.jms.JmsConstants;
 18  
 import org.mule.transport.jms.i18n.JmsMessages;
 19  
 import org.mule.util.ClassUtils;
 20  
 
 21  
 import java.lang.reflect.Method;
 22  
 import java.util.Hashtable;
 23  
 import java.util.Map;
 24  
 
 25  
 import javax.jms.ConnectionFactory;
 26  
 import javax.jms.JMSException;
 27  
 
 28  
 public class MuleMQJmsConnector extends JmsConnector
 29  
 {
 30  
     public static final String MULEMQ_CONNECTION_FACTORY_CLASS = "com.pcbsys.nirvana.nJMS.ConnectionFactoryImpl";
 31  
 
 32  
     // The default values for the connection factory properties
 33  
     public static final String DEFAULT_REALM_URL = "nsp://localhost:9000";
 34  
     public static final String DEFAULT_BUFFER_OUTPUT = "queued";
 35  
     public static final boolean DEFAULT_SYNC_WRITES = false;
 36  
     public static final int DEFAULT_SYNC_BATCH_SIZE = 50;
 37  
     public static final int DEFAULT_SYNC_TIME = 20;
 38  
     public static final int DEFAULT_GLOBAL_STORE_CAPACITY = 5000;
 39  
     public static final int DEFAULT_MAX_UNACKED_SIZE = 100;
 40  
     public static final boolean DEFAULT_USE_JMS_ENGINE = true;
 41  
     public static final int DEFAULT_QUEUE_WINDOW_SIZE = 100;
 42  
     public static final int DEFAULT_AUTO_ACK_COUNT = 50;
 43  
     public static final boolean DEFAULT_ENABLE_SHARED_DURABLE = false;
 44  
     public static final boolean DEFAULT_RANDOMISE_R_NAMES = false;
 45  
     public static final int DEFAULT_MAX_REDELIVERY = 100;
 46  
     public static final int DEFAULT_MESSAGE_THREAD_POOL_SIZE = 30;
 47  
     public static final boolean DEFAULT_DISC_ON_CLUSTER_FAILURE = true;
 48  
     public static final int DEFAULT_INITIAL_RETRY_COUNT = 2;
 49  
     public static final boolean DEFAULT_RETRY_COMMIT = false;
 50  
     public static final boolean DEFAULT_ENABLE_MULTIPLEXED_CONNECTIONS = false;
 51  
 
 52  
     // properties to be set on the connector all initialised to their respective
 53  
     // default value
 54  0
     private String realmURL = DEFAULT_REALM_URL;
 55  0
     private String bufferOutput = DEFAULT_BUFFER_OUTPUT;
 56  0
     private boolean syncWrites = DEFAULT_SYNC_WRITES;
 57  0
     private int syncBatchSize = DEFAULT_SYNC_BATCH_SIZE;
 58  0
     private int syncTime = DEFAULT_SYNC_TIME;
 59  0
     private int globalStoreCapacity = DEFAULT_GLOBAL_STORE_CAPACITY;
 60  0
     private int maxUnackedSize = DEFAULT_MAX_UNACKED_SIZE;
 61  0
     private boolean useJMSEngine = DEFAULT_USE_JMS_ENGINE;
 62  0
     private int queueWindowSize = DEFAULT_QUEUE_WINDOW_SIZE;
 63  0
     private int autoAckCount = DEFAULT_AUTO_ACK_COUNT;
 64  0
     private boolean enableSharedDurable = DEFAULT_ENABLE_SHARED_DURABLE;
 65  0
     private boolean randomiseRNames = DEFAULT_RANDOMISE_R_NAMES;
 66  0
     private int muleMqMaxRedelivery = DEFAULT_MAX_REDELIVERY;
 67  0
     private int messageThreadPoolSize = DEFAULT_MESSAGE_THREAD_POOL_SIZE;
 68  0
     private boolean discOnClusterFailure = DEFAULT_DISC_ON_CLUSTER_FAILURE;
 69  0
     private int initialRetryCount = DEFAULT_INITIAL_RETRY_COUNT;
 70  0
     private boolean retryCommit = DEFAULT_RETRY_COMMIT;
 71  0
     private boolean enableMultiplexedConnections = DEFAULT_ENABLE_MULTIPLEXED_CONNECTIONS;
 72  
 
 73  
     // property names
 74  
     protected static final String BUFFER_OUTPUT = "BufferOutput";
 75  
     protected static final String SYNC_WRITES = "nirvana.syncWrites";
 76  
     protected static final String SYNC_BATCH_SIZE = "nirvana.syncBatchSize";
 77  
     protected static final String SYNC_TIME = "nirvana.syncTime";
 78  
     protected static final String GLOBAL_STORE_CAPACITY = "nirvana.globalStoreCapacity";
 79  
     protected static final String MAX_UNACKED_SIZE = "nirvana.maxUnackedSize";
 80  
     protected static final String USE_JMS_ENGINE = "nirvana.useJMSEngine";
 81  
     protected static final String QUEUE_WINDOW_SIZE = "nirvana.queueWindowSize";
 82  
     protected static final String AUTO_ACK_COUNT = "nirvana.autoAckCount";
 83  
     protected static final String ENABLE_SHARED_DURABLE = "nirvana.enableSharedDurable";
 84  
     protected static final String RANDOMISE_R_NAMES = "nirvana.randomiseRNames";
 85  
     protected static final String MAX_REDELIVERY = "nirvana.maxRedelivery";
 86  
     protected static final String MESSAGE_THREAD_POOL_SIZE = "nirvana.messageThreadPoolSize";
 87  
     protected static final String DISC_ON_CLUSTER_FAILURE = "nirvana.discOnClusterFailure";
 88  
     protected static final String INITIAL_RETRY_COUNT = "nirvana.initialRetryCount";
 89  
     protected static final String RETRY_COMMIT = "nirvana.retryCommit";
 90  
     protected static final String ENABLE_MULTIPLEXED_CONNECTIONS = "nirvana.enableMultiplexedConnections";
 91  
 
 92  0
     public boolean supportJms102bSpec = false;
 93  
 
 94  0
     private boolean inCluster = false;
 95  
     
 96  
     public MuleMQJmsConnector(MuleContext context)
 97  
     {
 98  0
         super(context);
 99  0
         super.setSpecification(JmsConstants.JMS_SPECIFICATION_11);
 100  0
     }
 101  
 
 102  
     public boolean isSupportJms102bSpec()
 103  
     {
 104  0
         return supportJms102bSpec;
 105  
     }
 106  
 
 107  
     public void setSupportJms102bSpec(boolean supportJms102bSpec)
 108  
     {
 109  0
         this.supportJms102bSpec = supportJms102bSpec;
 110  0
     }
 111  
 
 112  
     /*
 113  
      * We need to default the specification to 1.1, the xsd defaults to 1.0.2b, we
 114  
      * wouldn't have to do this here if the default was set in JmsConnector only, In
 115  
      * that case setting the default in the constructor would have been sufficient.
 116  
      */
 117  
     @Override
 118  
     public void setSpecification(String specification)
 119  
     {
 120  0
         if (!isSupportJms102bSpec() && specification.equals(JmsConstants.JMS_SPECIFICATION_102B))
 121  
         {
 122  0
             logger.warn(JmsMessages.errorMuleMqJmsSpecification());
 123  0
             specification = JmsConstants.JMS_SPECIFICATION_11;
 124  
         }
 125  0
         super.setSpecification(specification);
 126  0
     }
 127  
 
 128  
     @Override
 129  
     protected void doInitialise() throws InitialisationException
 130  
     {
 131  0
         if (!isSupportJms102bSpec() && getSpecification().equals(JmsConstants.JMS_SPECIFICATION_102B))
 132  
         {
 133  0
             throw new InitialisationException(JmsMessages.errorMuleMqJmsSpecification(), this);
 134  
         }
 135  0
         super.doInitialise();
 136  0
     }
 137  
 
 138  
     @Override
 139  
     protected ConnectionFactory getDefaultConnectionFactory() throws Exception
 140  
     {
 141  0
         ConnectionFactory connectionFactory = (ConnectionFactory) ClassUtils.instanciateClass(
 142  
             getMuleMQFactoryClass(), getRealmURL());
 143  0
         applyVendorSpecificConnectionFactoryProperties(connectionFactory);
 144  0
         return connectionFactory;
 145  
     }
 146  
 
 147  
     private void applyVendorSpecificConnectionFactoryProperties(ConnectionFactory connectionFactory)
 148  
     {
 149  
         // set the properties first on the prop hash table
 150  0
         Hashtable<String, Object> props = new Hashtable<String, Object>();
 151  0
         props.put(BUFFER_OUTPUT, bufferOutput);
 152  0
         props.put(SYNC_WRITES, Boolean.toString(syncWrites));
 153  0
         props.put(SYNC_BATCH_SIZE, Integer.toString(syncBatchSize));
 154  0
         props.put(SYNC_TIME, Integer.toString(syncTime));
 155  0
         props.put(GLOBAL_STORE_CAPACITY, Integer.toString(globalStoreCapacity));
 156  0
         props.put(MAX_UNACKED_SIZE, Integer.toString(maxUnackedSize));
 157  0
         props.put(USE_JMS_ENGINE, Boolean.toString(useJMSEngine));
 158  0
         props.put(QUEUE_WINDOW_SIZE, Integer.toString(queueWindowSize));
 159  0
         props.put(AUTO_ACK_COUNT, Integer.toString(autoAckCount));
 160  0
         props.put(ENABLE_SHARED_DURABLE, Boolean.toString(enableSharedDurable));
 161  0
         props.put(RANDOMISE_R_NAMES, Boolean.toString(randomiseRNames));
 162  0
         props.put(MAX_REDELIVERY, Integer.toString(muleMqMaxRedelivery));
 163  0
         props.put(MESSAGE_THREAD_POOL_SIZE, Integer.toString(messageThreadPoolSize));
 164  0
         props.put(DISC_ON_CLUSTER_FAILURE, Boolean.toString(discOnClusterFailure));
 165  0
         props.put(INITIAL_RETRY_COUNT, Integer.toString(initialRetryCount));
 166  0
         props.put(RETRY_COMMIT, Boolean.toString(retryCommit));
 167  0
         props.put(ENABLE_MULTIPLEXED_CONNECTIONS, Boolean.toString(enableMultiplexedConnections));
 168  
 
 169  
         // if the user used the connectionFactoryProperties map, these will override
 170  
         // the properties on the connector
 171  0
         Map<String, Object> connectionFactoryProperties = getConnectionFactoryProperties();
 172  0
         if (connectionFactoryProperties != null)
 173  
         {
 174  0
             props.putAll(connectionFactoryProperties);
 175  
         }
 176  
 
 177  
         try
 178  
         {
 179  
             // use reflection to set the properties on the connection factory
 180  0
             Method setPropertiesMethod = connectionFactory.getClass().getMethod("setProperties",
 181  
                 Hashtable.class);
 182  0
             setPropertiesMethod.invoke(connectionFactory, props);
 183  
         }
 184  0
         catch (Exception e)
 185  
         {
 186  0
             logger.error("Can not set properties on the MuleMQ connection factory " + e);
 187  0
         }
 188  0
     }
 189  
 
 190  
     // returns the connection factory class name as a string. This method will be
 191  
     // used by getDefaultConnectionFactory() to acquire the appropriate class to
 192  
     // initialise
 193  
     protected String getMuleMQFactoryClass()
 194  
     {
 195  0
         return MULEMQ_CONNECTION_FACTORY_CLASS;
 196  
     }
 197  
 
 198  
     public String getRealmURL()
 199  
     {
 200  0
         return realmURL;
 201  
     }
 202  
 
 203  
     public void setRealmURL(String realmURL)
 204  
     {
 205  0
         this.realmURL = realmURL;
 206  0
         if (realmURL != null)
 207  
         {
 208  0
             String[] realms = realmURL.split(",");
 209  0
             if (realms != null && realms.length > 1)
 210  
             {
 211  0
                 this.setInCluster(true);
 212  
             }
 213  
         }
 214  0
     }
 215  
 
 216  
     public String getBufferOutput()
 217  
     {
 218  0
         return bufferOutput;
 219  
     }
 220  
 
 221  
     public void setBufferOutput(String bufferOutput)
 222  
     {
 223  0
         this.bufferOutput = bufferOutput;
 224  0
     }
 225  
 
 226  
     public boolean isSyncWrites()
 227  
     {
 228  0
         return syncWrites;
 229  
     }
 230  
 
 231  
     public void setSyncWrites(boolean syncWrites)
 232  
     {
 233  0
         this.syncWrites = syncWrites;
 234  0
     }
 235  
 
 236  
     public int getSyncBatchSize()
 237  
     {
 238  0
         return syncBatchSize;
 239  
     }
 240  
 
 241  
     public void setSyncBatchSize(int syncBatchSize)
 242  
     {
 243  0
         this.syncBatchSize = syncBatchSize;
 244  0
     }
 245  
 
 246  
     public int getSyncTime()
 247  
     {
 248  0
         return syncTime;
 249  
     }
 250  
 
 251  
     public void setSyncTime(int syncTime)
 252  
     {
 253  0
         this.syncTime = syncTime;
 254  0
     }
 255  
 
 256  
     public int getGlobalStoreCapacity()
 257  
     {
 258  0
         return globalStoreCapacity;
 259  
     }
 260  
 
 261  
     public void setGlobalStoreCapacity(int globalStoreCapacity)
 262  
     {
 263  0
         this.globalStoreCapacity = globalStoreCapacity;
 264  0
     }
 265  
 
 266  
     public int getMaxUnackedSize()
 267  
     {
 268  0
         return maxUnackedSize;
 269  
     }
 270  
 
 271  
     public void setMaxUnackedSize(int maxUnackedSize)
 272  
     {
 273  0
         this.maxUnackedSize = maxUnackedSize;
 274  0
     }
 275  
 
 276  
     public boolean isUseJMSEngine()
 277  
     {
 278  0
         return useJMSEngine;
 279  
     }
 280  
 
 281  
     public void setUseJMSEngine(boolean useJMSEngine)
 282  
     {
 283  0
         this.useJMSEngine = useJMSEngine;
 284  0
     }
 285  
 
 286  
     public int getQueueWindowSize()
 287  
     {
 288  0
         return queueWindowSize;
 289  
     }
 290  
 
 291  
     public void setQueueWindowSize(int queueWindowSize)
 292  
     {
 293  0
         this.queueWindowSize = queueWindowSize;
 294  0
     }
 295  
 
 296  
     public int getAutoAckCount()
 297  
     {
 298  0
         return autoAckCount;
 299  
     }
 300  
 
 301  
     public void setAutoAckCount(int autoAckCount)
 302  
     {
 303  0
         this.autoAckCount = autoAckCount;
 304  0
     }
 305  
 
 306  
     public boolean isEnableSharedDurable()
 307  
     {
 308  0
         return enableSharedDurable;
 309  
     }
 310  
 
 311  
     public void setEnableSharedDurable(boolean enableSharedDurable)
 312  
     {
 313  0
         this.enableSharedDurable = enableSharedDurable;
 314  0
     }
 315  
 
 316  
     public boolean isRandomiseRNames()
 317  
     {
 318  0
         return randomiseRNames;
 319  
     }
 320  
 
 321  
     public void setRandomiseRNames(boolean randomiseRNames)
 322  
     {
 323  0
         this.randomiseRNames = randomiseRNames;
 324  0
     }
 325  
 
 326  
     public int getMessageThreadPoolSize()
 327  
     {
 328  0
         return messageThreadPoolSize;
 329  
     }
 330  
 
 331  
     public void setMessageThreadPoolSize(int messageThreadPoolSize)
 332  
     {
 333  0
         this.messageThreadPoolSize = messageThreadPoolSize;
 334  0
     }
 335  
 
 336  
     public boolean isDiscOnClusterFailure()
 337  
     {
 338  0
         return discOnClusterFailure;
 339  
     }
 340  
 
 341  
     public void setDiscOnClusterFailure(boolean discOnClusterFailure)
 342  
     {
 343  0
         this.discOnClusterFailure = discOnClusterFailure;
 344  0
     }
 345  
 
 346  
     public int getInitialRetryCount()
 347  
     {
 348  0
         return initialRetryCount;
 349  
     }
 350  
 
 351  
     public void setInitialRetryCount(int initialRetryCount)
 352  
     {
 353  0
         this.initialRetryCount = initialRetryCount;
 354  0
     }
 355  
 
 356  
     public int getMuleMqMaxRedelivery()
 357  
     {
 358  0
         return muleMqMaxRedelivery;
 359  
     }
 360  
 
 361  
     public void setMuleMqMaxRedelivery(int mulqMqMaxRedelivery)
 362  
     {
 363  0
         this.muleMqMaxRedelivery = mulqMqMaxRedelivery;
 364  0
     }
 365  
 
 366  
     public void setRetryCommit(boolean retryCommit)
 367  
     {
 368  0
         this.retryCommit = retryCommit;
 369  0
     }
 370  
 
 371  
     public boolean isRetryCommit()
 372  
     {
 373  0
         return retryCommit;
 374  
     }
 375  
 
 376  
     public boolean isEnableMultiplexedConnections()
 377  
     {
 378  0
         return enableMultiplexedConnections;
 379  
     }
 380  
 
 381  
     public void setEnableMultiplexedConnections(boolean enableMultiplexedConnections)
 382  
     {
 383  0
         this.enableMultiplexedConnections = enableMultiplexedConnections;
 384  0
     }
 385  
 
 386  
     public boolean isInCluster()
 387  
     {
 388  0
         return inCluster;
 389  
     }
 390  
 
 391  
     public void setInCluster(boolean inCluster)
 392  
     {
 393  0
         this.inCluster = inCluster;
 394  0
     }
 395  
 
 396  
     public void onException(JMSException jmsException)
 397  
     {
 398  0
         Throwable th = ExceptionHelper.getRootException(jmsException);
 399  0
         if (th == null) th = jmsException;
 400  0
         String errMsg = th.getMessage();
 401  
 
 402  0
         if (errMsg.contains("Channel is full :"))
 403  
         {
 404  0
             if(logger.isWarnEnabled())
 405  
             {
 406  
                 // TODO : externalize strings
 407  0
                 StringBuffer msg = new StringBuffer("MuleMQJmsConnector.onException() received exception: ");
 408  0
                 msg.append(th.getMessage());
 409  0
                 msg.append("Older Messages will be discarded by MULE MQ.To prevent message loss use transacted outbound-endpoint");
 410  0
                 msg.append("Refer to 'Queue Capacity' at http://www.mulesoft.org/display/MQ/Configuring+Mule+MQ#ConfiguringMuleMQ-ConfiguringQueues");
 411  
                 // This error does not mean that connection has been closed. Log Capacity
 412  
                 // is full warn and return.
 413  0
                 logger.warn(msg.toString(),th);
 414  0
             }
 415  
         }
 416  0
         else if (this.isInCluster() && errMsg.contains("Disconnected from :"))
 417  
         {
 418  
             // TODO : externalize strings
 419  0
             StringBuffer msg = new StringBuffer("MuleMQJmsConnector.onException() received exception: ");
 420  0
             msg.append(th.getMessage());
 421  0
             msg.append("If using Mule MQ in a cluster Mule ESB will reconnect automatically in a few seconds");
 422  
             // Nothing to do here, log error and return
 423  0
             logger.warn(msg.toString(),th);
 424  0
         }
 425  0
         else if (this.isInCluster() && errMsg.contains("Reconnected to :"))
 426  
         {
 427  
             // TODO : externalize strings
 428  0
             StringBuffer msg = new StringBuffer("MuleMQJmsConnector.onException() received exception: ");
 429  0
             msg.append(th.getMessage());
 430  0
             msg.append("If using Mule MQ in a cluster Mule ESB will reconnect automatically in a few seconds");
 431  
             // Nothing to do here, log message and return
 432  0
             logger.warn(msg.toString(),th);
 433  0
         }
 434  
         else
 435  
         {
 436  
             // This is connection error in a single node server. Follow regular
 437  
             // connection error logic
 438  0
             super.onException(jmsException);
 439  
         }
 440  0
     }
 441  
 }