View Javadoc
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.redelivery;
8   
9   import org.mule.config.i18n.CoreMessages;
10  import org.mule.transport.jms.JmsConnector;
11  import org.mule.transport.jms.JmsConstants;
12  
13  import java.util.Enumeration;
14  import java.util.concurrent.atomic.AtomicReference;
15  
16  import javax.jms.ConnectionMetaData;
17  import javax.jms.JMSException;
18  
19  import org.apache.commons.logging.Log;
20  import org.apache.commons.logging.LogFactory;
21  
22  /**
23   * This factory will consult JMS connection metadata for supported optional properties and use
24   * those, if available, otherwise falling back to the manual counting of redeliveries.
25   *
26   * @see CountingRedeliveryHandlerFactory
27   * @see org.mule.transport.jms.redelivery.JmsXRedeliveryHandlerFactory
28   * @see javax.jms.ConnectionMetaData
29   */
30  public class AutoDiscoveryRedeliveryHandlerFactory implements RedeliveryHandlerFactory
31  {
32      protected final Log logger = LogFactory.getLog(getClass());
33  
34      protected AtomicReference<RedeliveryHandler> delegateHandler = new AtomicReference<RedeliveryHandler>(null);
35  
36      protected JmsConnector connector;
37  
38      public AutoDiscoveryRedeliveryHandlerFactory(JmsConnector connector)
39      {
40          if (connector == null)
41          {
42              throw new IllegalArgumentException(CoreMessages.objectIsNull("connector").getMessage());
43          }
44          this.connector = connector;
45      }
46  
47      public RedeliveryHandler create()
48      {
49          RedeliveryHandler result;
50  
51          // initialize, accounting for concurrency
52          if (delegateHandler.get() == null)
53          {
54              RedeliveryHandler newInstance = createInstance();
55              boolean ok = delegateHandler.compareAndSet(null, newInstance);
56              if (!ok)
57              {
58                  // someone was faster to initialize it, use this ref instead
59                  result = delegateHandler.get();
60              }
61              else
62              {
63                  result = newInstance;
64              }
65          }
66          else
67          {
68              // just re-use existing handler
69              result = delegateHandler.get();
70          }
71  
72          return result;
73      }
74  
75      /**
76       * Create an instance using the discovery mechanism.
77       *
78       * @return an implementation based on the results of discovery
79       */
80      protected RedeliveryHandler createInstance()
81      {
82          RedeliveryHandler newInstance;
83          try
84          {
85              ConnectionMetaData metaData = connector.getConnection().getMetaData();
86              boolean supportsDeliveryCount = false;
87              final Enumeration propNames = metaData.getJMSXPropertyNames();
88              while (propNames.hasMoreElements())
89              {
90                  String p = (String) propNames.nextElement();
91                  if (JmsConstants.JMS_X_DELIVERY_COUNT.equals(p))
92                  {
93                      supportsDeliveryCount = true;
94                      break;
95                  }
96              }
97  
98              newInstance = (supportsDeliveryCount) ? new JmsXRedeliveryHandler() : new CountingRedeliveryHandler();
99          }
100         catch (JMSException e)
101         {
102             // fallback to defaults
103             newInstance = new CountingRedeliveryHandler();
104         }
105 
106         if (logger.isDebugEnabled())
107         {
108             logger.debug("Using " + newInstance.getClass().getName());
109         }
110 
111         return newInstance;
112     }
113 
114 }