View Javadoc

1   /*
2    * $Id: DefaultOutboundRouterCollection.java 21939 2011-05-18 13:32:09Z aperepel $
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.MessagingException;
15  import org.mule.api.MuleContext;
16  import org.mule.api.MuleEvent;
17  import org.mule.api.MuleMessage;
18  import org.mule.api.MuleSession;
19  import org.mule.api.lifecycle.Disposable;
20  import org.mule.api.lifecycle.Initialisable;
21  import org.mule.api.lifecycle.InitialisationException;
22  import org.mule.api.routing.MatchableMessageProcessor;
23  import org.mule.api.routing.OutboundRouter;
24  import org.mule.api.routing.OutboundRouterCatchAllStrategy;
25  import org.mule.api.routing.OutboundRouterCollection;
26  import org.mule.api.routing.RouterStatisticsRecorder;
27  import org.mule.api.routing.RoutingException;
28  import org.mule.api.routing.TransformingMatchable;
29  import org.mule.config.i18n.CoreMessages;
30  import org.mule.management.stats.RouterStatistics;
31  import org.mule.routing.AbstractCatchAllStrategy;
32  import org.mule.util.ObjectUtils;
33  
34  import java.util.Iterator;
35  import java.util.List;
36  import java.util.concurrent.CopyOnWriteArrayList;
37  
38  import org.apache.commons.logging.Log;
39  import org.apache.commons.logging.LogFactory;
40  
41  /**
42   * <code>DefaultOutboundRouterCollection</code> is a container of routers. An
43   * DefaultOutboundRouterCollection must have atleast one router. By default the first
44   * matching router is used to route an event though it is possible to match on all
45   * routers meaning that the message will get sent over all matching routers.
46   */
47  
48  public class DefaultOutboundRouterCollection implements OutboundRouterCollection
49  {
50  
51      /**
52       * logger used by this class
53       */
54      protected final transient Log logger = LogFactory.getLog(getClass());
55  
56      @SuppressWarnings("unchecked")
57      protected List<MatchableMessageProcessor> routers = new CopyOnWriteArrayList();
58      protected boolean matchAll = false;
59      private OutboundRouterCatchAllStrategy catchAllStrategy;
60  
61      protected RouterStatistics statistics = new RouterStatistics(RouterStatistics.TYPE_OUTBOUND);
62      protected MuleContext muleContext;
63  
64      public MuleEvent process(final MuleEvent event) throws MessagingException
65      {
66          MuleMessage message = event.getMessage();
67          MuleSession session = event.getSession();
68          MuleEvent result;
69          boolean matchfound = false;
70  
71          for (Iterator<MatchableMessageProcessor> iterator = getRoutes().iterator(); iterator.hasNext();)
72          {
73              OutboundRouter outboundRouter = (OutboundRouter) iterator.next();
74  
75              final MuleMessage outboundRouterMessage;
76              // Create copy of message for router 1..n-1 if matchAll="true" or if
77              // routers require copy because it may mutate payload before match is
78              // chosen
79              if (iterator.hasNext()
80                  && (isMatchAll() || ((outboundRouter instanceof TransformingMatchable) && ((TransformingMatchable) outboundRouter).isTransformBeforeMatch())))
81              {
82                  if (((DefaultMuleMessage) message).isConsumable())
83                  {
84                      throw new MessagingException(CoreMessages.cannotCopyStreamPayload(message.getPayload()
85                          .getClass()
86                          .getName()), event);
87                  }
88                  outboundRouterMessage = new DefaultMuleMessage(message.getPayload(), message, muleContext);
89              }
90              else
91              {
92                  outboundRouterMessage = message;
93              }
94  
95              try
96              {
97                  if (outboundRouter.isMatch(outboundRouterMessage))
98                  {
99                      matchfound = true;
100                     // Manage outbound only transactions here
101                     final OutboundRouter router = outboundRouter;
102     
103                     result = router.process(event);
104     
105                     if (!isMatchAll())
106                     {
107                         return result;
108                     }
109                 }
110             }
111             catch (MessagingException e)
112             {
113                 throw e;
114             }
115             catch (Exception e)
116             {
117                 throw new RoutingException(event, outboundRouter, e);
118             }
119         }
120 
121         if (!matchfound && getCatchAllStrategy() != null)
122         {
123             if (logger.isDebugEnabled())
124             {
125                 logger.debug("Message did not match any routers on: " + session.getFlowConstruct().getName()
126                              + " invoking catch all strategy");
127             }
128             return catchAll(event);
129         }
130         else if (!matchfound)
131         {
132             logger.warn("Message did not match any routers on: "
133                         + session.getFlowConstruct().getName()
134                         + " and there is no catch all strategy configured on this router.  Disposing message "
135                         + message);
136         }
137         return event;
138     }
139 
140     protected MuleEvent catchAll(MuleEvent event) throws RoutingException
141     {
142         if (getRouterStatistics().isEnabled())
143         {
144             getRouterStatistics().incrementCaughtMessage();
145         }
146 
147         return getCatchAllStrategy().process(event);
148     }
149 
150     public void initialise() throws InitialisationException
151     {
152         for (MatchableMessageProcessor router : routers)
153         {
154             if (router instanceof Initialisable)
155             {
156                 ((Initialisable) router).initialise();
157             }
158         }
159     }
160 
161     public void dispose()
162     {
163         for (MatchableMessageProcessor router : routers)
164         {
165             if (router instanceof Disposable)
166             {
167                 ((Disposable) router).dispose();
168             }
169         }
170     }
171     
172     // TODO Use spring factory bean
173     @Deprecated
174     public void setMessageProcessors(List<MatchableMessageProcessor> routers)
175     {
176         for (MatchableMessageProcessor router : routers)
177         {
178             addRoute(router);
179         }
180     }
181     
182     public void addRoute(MatchableMessageProcessor router)
183     {
184         if (router instanceof RouterStatisticsRecorder)
185         {
186             ((RouterStatisticsRecorder) router).setRouterStatistics(getRouterStatistics());
187         }
188         routers.add(router);
189     }
190 
191     public void removeRoute(MatchableMessageProcessor router)
192     {
193         routers.remove(router);
194     }
195 
196     public List<MatchableMessageProcessor> getRoutes()
197     {
198         return routers;
199     }
200 
201     public OutboundRouterCatchAllStrategy getCatchAllStrategy()
202     {
203         return catchAllStrategy;
204     }
205 
206     public void setCatchAllStrategy(OutboundRouterCatchAllStrategy catchAllStrategy)
207     {
208         this.catchAllStrategy = catchAllStrategy;
209         if (this.catchAllStrategy != null && catchAllStrategy instanceof AbstractCatchAllStrategy)
210         {
211             ((AbstractCatchAllStrategy) this.catchAllStrategy).setRouterStatistics(statistics);
212         }
213     }
214 
215     public boolean isMatchAll()
216     {
217         return matchAll;
218     }
219 
220     public void setMatchAll(boolean matchAll)
221     {
222         this.matchAll = matchAll;
223     }
224 
225     public RouterStatistics getRouterStatistics()
226     {
227         return statistics;
228     }
229 
230     public void setRouterStatistics(RouterStatistics stat)
231     {
232         this.statistics = stat;
233     }
234 
235     public void setMuleContext(MuleContext context)
236     {
237         this.muleContext = context;
238     }
239 
240     public boolean hasEndpoints()
241     {
242         for (Iterator iterator = routers.iterator(); iterator.hasNext();)
243         {
244             OutboundRouter router = (OutboundRouter) iterator.next();
245             if (router.getRoutes().size() > 0 || router.isDynamicRoutes())
246             {
247                 return true;
248             }
249         }
250         return false;
251     }
252 
253     @Override
254     public String toString()
255     {
256         return ObjectUtils.toString(this);
257     }
258 }