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.construct.builder;
8   
9   import java.util.Arrays;
10  
11  import org.mule.MessageExchangePattern;
12  import org.mule.api.MuleContext;
13  import org.mule.api.MuleException;
14  import org.mule.api.endpoint.EndpointBuilder;
15  import org.mule.api.endpoint.InboundEndpoint;
16  import org.mule.api.endpoint.OutboundEndpoint;
17  import org.mule.api.processor.MessageProcessor;
18  import org.mule.api.transaction.TransactionConfig;
19  import org.mule.api.transaction.TransactionException;
20  import org.mule.api.transaction.TransactionFactory;
21  import org.mule.api.transformer.Transformer;
22  import org.mule.config.i18n.MessageFactory;
23  import org.mule.construct.Bridge;
24  import org.mule.transaction.MuleTransactionConfig;
25  import org.mule.transaction.XaTransactionFactory;
26  import org.mule.util.ClassUtils;
27  import org.mule.util.StringUtils;
28  
29  public class BridgeBuilder extends
30      AbstractFlowConstructWithSingleInboundAndOutboundEndpointBuilder<BridgeBuilder, Bridge>
31  {
32      protected MessageExchangePattern exchangePattern = MessageExchangePattern.REQUEST_RESPONSE;
33      protected boolean transacted = false;
34  
35      @Override
36      protected MessageExchangePattern getInboundMessageExchangePattern()
37      {
38          return exchangePattern;
39      }
40  
41      @Override
42      protected MessageExchangePattern getOutboundMessageExchangePattern()
43      {
44          return exchangePattern;
45      }
46  
47      public BridgeBuilder exchangePattern(MessageExchangePattern exchangePattern)
48      {
49          this.exchangePattern = exchangePattern;
50          return this;
51      }
52  
53      public BridgeBuilder transacted(boolean transacted)
54      {
55          this.transacted = transacted;
56          return this;
57      }
58  
59      public BridgeBuilder inboundTransformers(Transformer... transformers)
60      {
61          this.inboundTransformers = Arrays.asList((MessageProcessor[]) transformers);
62          return this;
63      }
64  
65      public BridgeBuilder inboundResponseTransformers(Transformer... responseTransformers)
66      {
67          this.inboundResponseTransformers = Arrays.asList((MessageProcessor[]) responseTransformers);
68          return this;
69      }
70  
71      @Override
72      protected void doConfigureInboundEndpointBuilder(MuleContext muleContext, EndpointBuilder endpointBuilder)
73      {
74          if (transacted)
75          {
76              MuleTransactionConfig transactionConfig = new MuleTransactionConfig();
77              transactionConfig.setMuleContext(muleContext);
78              transactionConfig.setAction(TransactionConfig.ACTION_BEGIN_OR_JOIN);
79              endpointBuilder.setTransactionConfig(transactionConfig);
80          }
81      }
82  
83      @Override
84      protected void doConfigureOutboundEndpointBuilder(MuleContext muleContext, EndpointBuilder endpointBuilder)
85      {
86          if (transacted)
87          {
88              MuleTransactionConfig transactionConfig = new MuleTransactionConfig();
89              transactionConfig.setMuleContext(muleContext);
90              transactionConfig.setAction(TransactionConfig.ACTION_ALWAYS_JOIN);
91              endpointBuilder.setTransactionConfig(transactionConfig);
92          }
93      }
94  
95      @Override
96      protected Bridge buildFlowConstruct(MuleContext muleContext) throws MuleException
97      {
98          InboundEndpoint inboundEndpoint = getOrBuildInboundEndpoint(muleContext);
99          OutboundEndpoint outboundEndpoint = getOrBuildOutboundEndpoint(muleContext);
100 
101         if (transacted)
102         {
103             setTransactionFactoriesIfNeeded(inboundEndpoint, outboundEndpoint);
104         }
105 
106         return new Bridge(name, muleContext, inboundEndpoint, outboundEndpoint, exchangePattern, transacted);
107     }
108 
109     private void setTransactionFactoriesIfNeeded(InboundEndpoint inboundEndpoint,
110                                                  OutboundEndpoint outboundEndpoint) throws MuleException
111     {
112         String inboundProtocol = inboundEndpoint.getConnector().getProtocol();
113         String outboundProtocol = outboundEndpoint.getConnector().getProtocol();
114 
115         boolean needXA = !inboundProtocol.equals(outboundProtocol);
116 
117         TransactionConfig inboundTransactionConfig = inboundEndpoint.getTransactionConfig();
118 
119         if (inboundTransactionConfig.getFactory() == null)
120         {
121             TransactionFactory transactionFactory = needXA
122                                                           ? new XaTransactionFactory()
123                                                           : getTransactionFactory(inboundProtocol);
124 
125             inboundTransactionConfig.setFactory(transactionFactory);
126         }
127 
128         TransactionConfig outboundTransactionConfig = outboundEndpoint.getTransactionConfig();
129 
130         if (outboundTransactionConfig.getFactory() == null)
131         {
132             TransactionFactory transactionFactory = needXA
133                                                           ? new XaTransactionFactory()
134                                                           : getTransactionFactory(outboundProtocol);
135             outboundTransactionConfig.setFactory(transactionFactory);
136         }
137     }
138 
139     /**
140      * Very simplistic attempt to locate a protocol specific transaction factory.
141      */
142     private TransactionFactory getTransactionFactory(String protocol) throws MuleException
143     {
144         String protocolTransactionFactoryClassName = "org.mule.transport." + StringUtils.lowerCase(protocol)
145                                                      + "." + StringUtils.capitalize(protocol)
146                                                      + "TransactionFactory";
147 
148         if (!ClassUtils.isClassOnPath(protocolTransactionFactoryClassName, getClass()))
149         {
150             throw new TransactionException(
151                 MessageFactory.createStaticMessage("Failed to locate a transaction factory for protocol: "
152                                                    + protocol));
153         }
154 
155         try
156         {
157             return (TransactionFactory) ClassUtils.instanciateClass(protocolTransactionFactoryClassName);
158         }
159         catch (Exception e)
160         {
161             throw new TransactionException(
162                 MessageFactory.createStaticMessage("Failed to instantiate a transaction factory for protocol: "
163                                                    + protocol), e);
164         }
165     }
166 }