View Javadoc

1   /*
2    * $Id: AbstractRecipientList.java 11484 2008-03-22 19:28:25Z rossmason $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.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.MuleServer;
15  import org.mule.api.MuleException;
16  import org.mule.api.MuleMessage;
17  import org.mule.api.MuleSession;
18  import org.mule.api.endpoint.EndpointURI;
19  import org.mule.api.endpoint.OutboundEndpoint;
20  import org.mule.api.registry.RegistrationException;
21  import org.mule.api.routing.CouldNotRouteOutboundMessageException;
22  import org.mule.api.routing.RoutingException;
23  
24  import java.util.ArrayList;
25  import java.util.Iterator;
26  import java.util.List;
27  
28  import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
29  import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentMap;
30  
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  
34  /**
35   * <code>AbstractRecipientList</code> is used to dispatch a single event to
36   * multiple recipients over the same transport. The recipient endpoints can be
37   * configured statically or can be obtained from the message payload.
38   */
39  
40  public abstract class AbstractRecipientList extends FilteringOutboundRouter
41  {
42      /**
43       * logger used by this class
44       */
45      protected final Log logger = LogFactory.getLog(getClass());
46  
47      private final ConcurrentMap recipientCache = new ConcurrentHashMap();
48  
49      private Boolean synchronous;
50  
51      public MuleMessage route(MuleMessage message, MuleSession session, boolean synchronous)
52          throws RoutingException
53      {
54          if(this.synchronous!=null)
55          {
56              synchronous = this.synchronous.booleanValue();
57          }
58  
59          List recipients = this.getRecipients(message);
60          List results = new ArrayList();
61  
62          if (enableCorrelation != ENABLE_CORRELATION_NEVER)
63          {
64              boolean correlationSet = message.getCorrelationGroupSize() != -1;
65              if (correlationSet && (enableCorrelation == ENABLE_CORRELATION_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          MuleMessage result = null;
77          OutboundEndpoint endpoint;
78          MuleMessage request;
79  
80          for (Iterator iterator = recipients.iterator(); iterator.hasNext();)
81          {
82              Object recipient = iterator.next();
83              // Make a copy of the message. Question is do we do a proper clone? in
84              // which case there
85              // would potentially be multiple messages with the same id...
86              request = new DefaultMuleMessage(message.getPayload(), message);
87              endpoint = this.getRecipientEndpoint(request, recipient);
88  
89              try
90              {
91                  if (synchronous)
92                  {
93                      result = this.send(session, request, endpoint);
94                      if (result != null)
95                      {
96                          results.add(result.getPayload());
97                      }
98                      else
99                      {
100                         if (logger.isDebugEnabled())
101                         {
102                             logger.debug("No result was returned for sync call to: "
103                                             + endpoint.getEndpointURI());
104                         }
105                     }
106                 }
107                 else
108                 {
109                     this.dispatch(session, request, endpoint);
110                 }
111             }
112             catch (MuleException e)
113             {
114                 throw new CouldNotRouteOutboundMessageException(request, endpoint, e);
115             }
116         }
117 
118         if (results.size() == 0)
119         {
120             return null;
121         }
122         else if (results.size() == 1)
123         {
124             return new DefaultMuleMessage(results.get(0), result);
125         }
126         else
127         {
128             return new DefaultMuleMessage(results, result);
129         }
130     }
131 
132     protected OutboundEndpoint getRecipientEndpoint(MuleMessage message, Object recipient) throws RoutingException
133     {
134         OutboundEndpoint endpoint = null;
135         try
136         {
137             if (recipient instanceof EndpointURI)
138             {
139                 endpoint = getRecipientEndpointFromUri((EndpointURI) recipient);
140             }
141             else if (recipient instanceof String)
142             {
143                 endpoint = getRecipientEndpointFromString(message, (String) recipient);
144             }
145             if (null == endpoint)
146             {
147                 throw new RegistrationException("Failed to create endpoint for: " + recipient);
148             }
149 
150             OutboundEndpoint existingEndpoint = (OutboundEndpoint) recipientCache.putIfAbsent(recipient, endpoint);
151             if (existingEndpoint != null)
152             {
153                 endpoint = existingEndpoint;
154             }
155         }
156         catch (MuleException e)
157         {
158             throw new RoutingException(message, endpoint, e);
159         }
160         return endpoint;
161     }
162 
163     protected OutboundEndpoint getRecipientEndpointFromUri(EndpointURI uri)
164             throws MuleException
165     {
166         OutboundEndpoint endpoint = null;
167         if (null != getMuleContext() && null != getMuleContext().getRegistry())
168         {
169             endpoint = getMuleContext().getRegistry().lookupEndpointFactory().getOutboundEndpoint(uri.getAddress());
170         }
171         if (null != endpoint)
172         {
173             MuleServer.getMuleContext().applyLifecycle(endpoint);
174         }
175         return endpoint;
176     }
177 
178     protected OutboundEndpoint getRecipientEndpointFromString(MuleMessage message, String recipient)
179             throws MuleException
180     {
181         OutboundEndpoint endpoint = (OutboundEndpoint) recipientCache.get(recipient);
182         if (null == endpoint && null != getMuleContext() && null != getMuleContext().getRegistry())
183         {
184             endpoint = getMuleContext().getRegistry().lookupEndpointFactory().getOutboundEndpoint(recipient);
185         }
186         return endpoint;
187     }
188 
189     public Boolean getSynchronous()
190     {
191         return synchronous;
192     }
193 
194     public void setSynchronous(Boolean synchronous)
195     {
196         this.synchronous = synchronous;
197     }
198 
199     public boolean isDynamicEndpoints()
200     {
201         return true;
202     }
203 
204     protected abstract List getRecipients(MuleMessage message);
205 
206 }