View Javadoc

1   /*
2    * $Id: AbstractOutboundRouter.java 10524 2008-01-24 19:20:11Z akuzmin $
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.MuleManager;
14  import org.mule.config.MuleProperties;
15  import org.mule.routing.AbstractRouter;
16  import org.mule.routing.CorrelationPropertiesExtractor;
17  import org.mule.transaction.TransactionCallback;
18  import org.mule.transaction.TransactionTemplate;
19  import org.mule.umo.UMOException;
20  import org.mule.umo.UMOMessage;
21  import org.mule.umo.UMOSession;
22  import org.mule.umo.UMOTransactionConfig;
23  import org.mule.umo.endpoint.UMOEndpoint;
24  import org.mule.umo.endpoint.UMOImmutableEndpoint;
25  import org.mule.umo.routing.RoutingException;
26  import org.mule.umo.routing.UMOOutboundRouter;
27  import org.mule.util.ClassUtils;
28  import org.mule.util.StringMessageUtils;
29  import org.mule.util.SystemUtils;
30  import org.mule.util.properties.PropertyExtractor;
31  
32  import java.util.Iterator;
33  import java.util.List;
34  
35  import edu.emory.mathcs.backport.java.util.concurrent.CopyOnWriteArrayList;
36  import org.apache.commons.logging.Log;
37  import org.apache.commons.logging.LogFactory;
38  
39  /**
40   * <code>AbstractOutboundRouter</code> is a base router class that tracks statistics
41   * about message processing through the router.
42   */
43  public abstract class AbstractOutboundRouter extends AbstractRouter implements UMOOutboundRouter
44  {
45      public static final int ENABLE_CORRELATION_IF_NOT_SET = 0;
46      public static final int ENABLE_CORRELATION_ALWAYS = 1;
47      public static final int ENABLE_CORRELATION_NEVER = 2;
48      /**
49       * logger used by this class
50       */
51      protected transient Log logger = LogFactory.getLog(getClass());
52  
53      protected List endpoints = new CopyOnWriteArrayList();
54  
55      protected String replyTo = null;
56  
57      protected int enableCorrelation = ENABLE_CORRELATION_IF_NOT_SET;
58  
59      protected PropertyExtractor propertyExtractor = new CorrelationPropertiesExtractor();
60  
61      protected UMOTransactionConfig transactionConfig;
62  
63      public void dispatch(final UMOSession session, final UMOMessage message, final UMOEndpoint endpoint) throws UMOException
64      {
65          setMessageProperties(session, message, endpoint);
66  
67          if (logger.isDebugEnabled())
68          {
69              try
70              {
71                  logger.debug("Message being sent to: " + endpoint.getEndpointURI() + " Message payload: \n"
72                               + StringMessageUtils.truncate(message.getPayloadAsString(), 100, false));
73              }
74              catch (Exception e)
75              {
76                  logger.debug("Message being sent to: " + endpoint.getEndpointURI()
77                               + " Message payload: \n(unable to retrieve payload: " + e.getMessage());
78              }
79          }
80  
81          TransactionTemplate tt = new TransactionTemplate(endpoint.getTransactionConfig(),
82                                                           session.getComponent().getDescriptor().getExceptionListener());
83  
84          TransactionCallback cb = new TransactionCallback()
85          {
86              public Object doInTransaction() throws Exception
87              {
88                  session.dispatchEvent(message, endpoint);
89                  return null;
90              }
91          };
92  
93          try
94          {
95              tt.execute(cb);
96          }
97          catch (Exception e)
98          {
99              throw new RoutingException(message, null, e);
100         }
101 
102         if (getRouterStatistics() != null)
103         {
104             if (getRouterStatistics().isEnabled())
105             {
106                 getRouterStatistics().incrementRoutedMessage(endpoint);
107             }
108         }
109     }
110 
111     public UMOMessage send(final UMOSession session, final UMOMessage message, final UMOEndpoint endpoint) throws UMOException
112     {
113         if (replyTo != null)
114         {
115             logger.debug("event was dispatched synchronously, but there is a ReplyTo endpoint set, so using asynchronous dispatch");
116             dispatch(session, message, endpoint);
117             return null;
118         }
119 
120         this.setMessageProperties(session, message, endpoint);
121 
122         if (logger.isDebugEnabled())
123         {
124             logger.debug("Message being sent to: " + endpoint.getEndpointURI());
125             logger.debug(message);
126         }
127 
128         if (logger.isTraceEnabled())
129         {
130             try
131             {
132                 logger.trace("Message payload: \n" + message.getPayloadAsString());
133             }
134             catch (Exception e)
135             {
136                 // ignore
137             }
138         }
139 
140         TransactionTemplate tt = new TransactionTemplate(endpoint.getTransactionConfig(),
141                                                          session.getComponent().getDescriptor().getExceptionListener());
142 
143         TransactionCallback cb = new TransactionCallback()
144         {
145             public Object doInTransaction() throws Exception
146             {
147                 return session.sendEvent(message, endpoint);
148             }
149         };
150 
151         UMOMessage result;
152         try
153         {
154             result = (UMOMessage) tt.execute(cb);
155         }
156         catch (Exception e)
157         {
158             throw new RoutingException(message, null, e);
159         }
160 
161         if (getRouterStatistics() != null)
162         {
163             if (getRouterStatistics().isEnabled())
164             {
165                 getRouterStatistics().incrementRoutedMessage(endpoint);
166             }
167         }
168 
169         if (logger.isDebugEnabled())
170         {
171             logger.debug("Response message from sending to: " + endpoint.getEndpointURI());
172             logger.debug(result);
173         }
174 
175         if (logger.isTraceEnabled())
176         {
177             try
178             {
179                 logger.trace("Message payload: \n" + result.getPayloadAsString());
180             }
181             catch (Exception e)
182             {
183                 // ignore
184             }
185         }
186 
187         return result;
188     }
189 
190     protected void setMessageProperties(UMOSession session, UMOMessage message, UMOEndpoint endpoint)
191     {
192         if (replyTo != null)
193         {
194             // if replyTo is set we'll probably want the correlationId set as
195             // well
196             message.setReplyTo(replyTo);
197             message.setProperty(MuleProperties.MULE_REPLY_TO_REQUESTOR_PROPERTY, session.getComponent()
198                 .getDescriptor()
199                 .getName());
200             if (logger.isDebugEnabled())
201             {
202                 logger.debug("Setting replyTo=" + replyTo + " for outbound endpoint: "
203                              + endpoint.getEndpointURI());
204             }
205         }
206         if (enableCorrelation != ENABLE_CORRELATION_NEVER)
207         {
208             boolean correlationSet = message.getCorrelationId() != null;
209             if (correlationSet && (enableCorrelation == ENABLE_CORRELATION_IF_NOT_SET))
210             {
211                 if (logger.isDebugEnabled())
212                 {
213                     logger.debug("CorrelationId is already set to '" + message.getCorrelationId()
214                                  + "' , not setting it again");
215                 }
216                 return;
217             }
218             else if (correlationSet)
219             {
220                 if (logger.isDebugEnabled())
221                 {
222                     logger.debug("CorrelationId is already set to '" + message.getCorrelationId()
223                                  + "', but router is configured to overwrite it");
224                 }
225             }
226             else
227             {
228                 if (logger.isDebugEnabled())
229                 {
230                     logger.debug("No CorrelationId is set on the message, will set a new Id");
231                 }
232             }
233 
234             String correlation;
235             Object o = propertyExtractor.getProperty(MuleProperties.MULE_CORRELATION_ID_PROPERTY, message);
236             if (logger.isDebugEnabled())
237             {
238                 logger.debug("Extracted correlation Id as: " + o);
239             }
240             correlation = o.toString();
241 
242             if (logger.isDebugEnabled())
243             {
244                 StringBuffer buf = new StringBuffer();
245                 buf.append("Setting Correlation info on Outbound router for endpoint: ").append(
246                     endpoint.getEndpointURI());
247                 buf.append(SystemUtils.LINE_SEPARATOR).append("Id=").append(correlation);
248                 // buf.append(", ").append("Seq=").append(seq);
249                 // buf.append(", ").append("Group Size=").append(group);
250                 logger.debug(buf.toString());
251             }
252             message.setCorrelationId(correlation);
253             // message.setCorrelationGroupSize(group);
254             // message.setCorrelationSequence(seq);
255         }
256     }
257 
258     public List getEndpoints()
259     {
260         return endpoints;
261     }
262 
263     public void setEndpoints(List endpoints)
264     {
265         // this.endpoints = new CopyOnWriteArrayList(endpoints);
266         for (Iterator iterator = endpoints.iterator(); iterator.hasNext();)
267         {
268             UMOEndpoint umoEndpoint = (UMOEndpoint) iterator.next();
269             addEndpoint(umoEndpoint);
270         }
271     }
272 
273     public void addEndpoint(UMOEndpoint endpoint)
274     {
275         endpoint.setType(UMOEndpoint.ENDPOINT_TYPE_SENDER);
276         endpoints.add(endpoint);
277     }
278 
279     public boolean removeEndpoint(UMOImmutableEndpoint endpoint)
280     {
281         return endpoints.remove(endpoint);
282     }
283 
284     public String getReplyTo()
285     {
286         return replyTo;
287     }
288 
289     public void setReplyTo(String replyTo)
290     {
291         if (replyTo != null)
292         {
293             this.replyTo = MuleManager.getInstance().lookupEndpointIdentifier(replyTo, replyTo);
294         }
295         else
296         {
297             this.replyTo = null;
298         }
299     }
300 
301     public int getEnableCorrelation()
302     {
303         return enableCorrelation;
304     }
305 
306     public void setEnableCorrelation(int enableCorrelation)
307     {
308         this.enableCorrelation = enableCorrelation;
309     }
310 
311     public void setEnableCorrelationAsString(String enableCorrelation)
312     {
313         if (enableCorrelation != null)
314         {
315             if (enableCorrelation.equals("ALWAYS"))
316             {
317                 this.enableCorrelation = ENABLE_CORRELATION_ALWAYS;
318             }
319             else if (enableCorrelation.equals("NEVER"))
320             {
321                 this.enableCorrelation = ENABLE_CORRELATION_NEVER;
322             }
323             else if (enableCorrelation.equals("IF_NOT_SET"))
324             {
325                 this.enableCorrelation = ENABLE_CORRELATION_IF_NOT_SET;
326             }
327             else
328             {
329                 throw new IllegalArgumentException("Value for enableCorrelation not recognised: "
330                                                    + enableCorrelation);
331             }
332         }
333     }
334 
335     public PropertyExtractor getPropertyExtractor()
336     {
337         return propertyExtractor;
338     }
339 
340     public void setPropertyExtractor(PropertyExtractor propertyExtractor)
341     {
342         this.propertyExtractor = propertyExtractor;
343     }
344 
345     public void setPropertyExtractorAsString(String className)
346     {
347         try
348         {
349             this.propertyExtractor = (PropertyExtractor) ClassUtils.instanciateClass(className, null,
350                 getClass());
351         }
352         catch (Exception ex)
353         {
354             throw (IllegalArgumentException) new IllegalArgumentException(
355                 "Couldn't instanciate property extractor class " + className).initCause(ex);
356         }
357     }
358 
359     public UMOTransactionConfig getTransactionConfig()
360     {
361         return transactionConfig;
362     }
363 
364     public void setTransactionConfig(UMOTransactionConfig transactionConfig)
365     {
366         this.transactionConfig = transactionConfig;
367     }
368 
369     public boolean isDynamicEndpoints()
370     {
371         return false;
372     }
373 }