View Javadoc

1   /*
2    * $Id: AbstractRecipientList.java 22601 2011-08-07 03:50:44Z mike.schilling $
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.routing.outbound;
12  
13  import org.mule.DefaultMuleMessage;
14  import org.mule.MessageExchangePattern;
15  import org.mule.api.DefaultMuleException;
16  import org.mule.api.MuleEvent;
17  import org.mule.api.MuleException;
18  import org.mule.api.MuleMessage;
19  import org.mule.api.endpoint.EndpointBuilder;
20  import org.mule.api.endpoint.EndpointURI;
21  import org.mule.api.endpoint.OutboundEndpoint;
22  import org.mule.api.registry.RegistrationException;
23  import org.mule.api.routing.CouldNotRouteOutboundMessageException;
24  import org.mule.api.routing.RoutingException;
25  import org.mule.config.i18n.MessageFactory;
26  import org.mule.routing.CorrelationMode;
27  
28  import java.util.ArrayList;
29  import java.util.List;
30  import java.util.concurrent.ConcurrentHashMap;
31  import java.util.concurrent.ConcurrentMap;
32  
33  /**
34   * <code>AbstractRecipientList</code> is used to dispatch a single event to
35   * multiple recipients over the same transport. The recipient targets can be
36   * configured statically or can be obtained from the message payload.
37   */
38  
39  public abstract class AbstractRecipientList extends FilteringOutboundRouter
40  {
41      private final ConcurrentMap<Object, OutboundEndpoint> recipientCache = new ConcurrentHashMap<Object, OutboundEndpoint>();
42  
43      private Boolean synchronous;
44  
45      @Override
46      public MuleEvent route(MuleEvent event) throws RoutingException
47      {
48          MuleMessage message = event.getMessage();
49  
50          List<Object> recipients = getRecipients(event);
51          List<MuleEvent> results = new ArrayList<MuleEvent>();
52  
53          if (enableCorrelation != CorrelationMode.NEVER)
54          {
55              boolean correlationSet = message.getCorrelationGroupSize() != -1;
56              if (correlationSet && (enableCorrelation == CorrelationMode.IF_NOT_SET))
57              {
58                  logger.debug("CorrelationId is already set, not setting Correlation group size");
59              }
60              else
61              {
62                  // the correlationId will be set by the AbstractOutboundRouter
63                  message.setCorrelationGroupSize(recipients.size());
64              }
65          }
66  
67          OutboundEndpoint endpoint = null;
68          for (Object recipient : recipients)
69          {
70              // Make a copy of the message. Question is do we do a proper clone? in
71              // which case there would potentially be multiple messages with the same id...
72              MuleMessage request = new DefaultMuleMessage(message.getPayload(), message, muleContext);
73              try
74              {
75                  endpoint = getRecipientEndpoint(request, recipient);
76  
77                  boolean sync =
78                      (this.synchronous == null ? endpoint.getExchangePattern().hasResponse() : this.synchronous.booleanValue());
79  
80                  if (sync)
81                  {
82                      results.add(sendRequest(event, request, endpoint, true));
83                  }
84                  else
85                  {
86                      sendRequest(event, request, endpoint, false);
87                  }
88              }
89              catch (MuleException e)
90              {
91                  throw new CouldNotRouteOutboundMessageException(event, endpoint, e);
92              }
93          }
94  
95          return resultsHandler.aggregateResults(results, event, muleContext);
96      }
97  
98      protected OutboundEndpoint getRecipientEndpoint(MuleMessage message, Object recipient) throws MuleException
99      {
100         OutboundEndpoint endpoint = null;
101         if (recipient instanceof OutboundEndpoint)
102         {
103             endpoint = (OutboundEndpoint) recipient;
104         }
105         else if (recipient instanceof EndpointURI)
106         {
107             endpoint = getRecipientEndpointFromUri((EndpointURI) recipient);
108         }
109         else if (recipient instanceof String)
110         {
111             endpoint = getRecipientEndpointFromString(message, (String) recipient);
112         }
113         if (null == endpoint)
114         {
115             throw new RegistrationException(MessageFactory.createStaticMessage("Failed to create endpoint for: " + recipient));
116         }
117 
118         OutboundEndpoint existingEndpoint = recipientCache.putIfAbsent(recipient, endpoint);
119         if (existingEndpoint != null)
120         {
121             endpoint = existingEndpoint;
122         }
123         return endpoint;
124     }
125 
126     protected OutboundEndpoint getRecipientEndpointFromUri(EndpointURI uri)
127             throws MuleException
128     {
129         OutboundEndpoint endpoint = null;
130         if (null != getMuleContext() && null != getMuleContext().getRegistry())
131         {
132             endpoint = buildOutboundEndpoint(uri.getAddress());
133         }
134         if (null != endpoint)
135         {
136             muleContext.getRegistry().applyLifecycle(endpoint);
137         }
138         return endpoint;
139     }
140 
141     protected OutboundEndpoint getRecipientEndpointFromString(MuleMessage message, String recipient)
142             throws MuleException
143     {
144         OutboundEndpoint endpoint = recipientCache.get(recipient);
145         if (null == endpoint && null != getMuleContext() && null != getMuleContext().getRegistry())
146         {
147             endpoint = buildOutboundEndpoint(recipient);
148         }
149         return endpoint;
150     }
151 
152     protected OutboundEndpoint buildOutboundEndpoint(String recipient) throws MuleException
153     {
154         EndpointBuilder endpointBuilder = getMuleContext().getEndpointFactory().getEndpointBuilder(recipient);
155 
156         try
157         {
158             endpointBuilder = (EndpointBuilder) endpointBuilder.clone();
159             endpointBuilder.setTransactionConfig(transactionConfig);
160             if (synchronous != null && synchronous)
161             {
162                 endpointBuilder.setExchangePattern(MessageExchangePattern.REQUEST_RESPONSE);
163             }
164         }
165         catch (CloneNotSupportedException e)
166         {
167             throw new DefaultMuleException(e);
168         }
169 
170         return endpointBuilder.buildOutboundEndpoint();
171     }
172 
173     public Boolean getSynchronous()
174     {
175         return synchronous;
176     }
177 
178     public void setSynchronous(Boolean synchronous)
179     {
180         this.synchronous = synchronous;
181     }
182 
183     @Override
184     public boolean isDynamicRoutes()
185     {
186         return true;
187     }
188 
189     protected abstract List<Object> getRecipients(MuleEvent event) throws CouldNotRouteOutboundMessageException;
190 
191 }