View Javadoc

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