View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.routing;
8   
9   import org.mule.DefaultMuleMessage;
10  import org.mule.OptimizedRequestContext;
11  import org.mule.api.MessagingException;
12  import org.mule.api.MuleEvent;
13  import org.mule.api.MuleException;
14  import org.mule.api.MuleMessage;
15  import org.mule.api.MuleSession;
16  import org.mule.api.lifecycle.Disposable;
17  import org.mule.api.lifecycle.Initialisable;
18  import org.mule.api.lifecycle.InitialisationException;
19  import org.mule.api.processor.MessageProcessor;
20  import org.mule.api.routing.MatchableMessageProcessor;
21  import org.mule.api.routing.MatchingRouter;
22  import org.mule.api.routing.TransformingMatchable;
23  import org.mule.config.i18n.CoreMessages;
24  
25  import java.util.Iterator;
26  import java.util.List;
27  
28  import edu.emory.mathcs.backport.java.util.concurrent.CopyOnWriteArrayList;
29  
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  
33  /**
34   * <code>AbstractRouterCollection</code> provides common method implementations of router collections for in
35   * and outbound routers.
36   */
37  
38  public class AbstractMatchingRouter implements MatchingRouter
39  {
40      /**
41       * logger used by this class
42       */
43      protected final transient Log logger = LogFactory.getLog(getClass());
44  
45      @SuppressWarnings("unchecked")
46      protected List<MatchableMessageProcessor> matchableRoutes = new CopyOnWriteArrayList();
47      protected boolean matchAll = false;
48      protected MessageProcessor defaultRoute;
49  
50      public MuleEvent process(MuleEvent event) throws MuleException
51      {
52          MuleMessage message = event.getMessage();
53          MuleSession session = event.getSession();
54          MuleEvent result;
55          boolean matchfound = false;
56  
57          for (Iterator iterator = matchableRoutes.iterator(); iterator.hasNext();)
58          {
59              MatchableMessageProcessor outboundRouter = (MatchableMessageProcessor) iterator.next();
60  
61              final MuleEvent eventToRoute;
62  
63              boolean copyEvent = false;
64              // Create copy of message for router 1..n-1 if matchAll="true" or if
65              // routers require copy because it may mutate payload before match is
66              // chosen
67              if (iterator.hasNext())
68              {
69                  if (isMatchAll())
70                  {
71                      copyEvent = true;
72                  }
73                  else if (outboundRouter instanceof TransformingMatchable)
74                  {
75                      copyEvent = ((TransformingMatchable) outboundRouter).isTransformBeforeMatch();
76                  }
77              }
78  
79              if (copyEvent)
80              {
81                  if (((DefaultMuleMessage) message).isConsumable())
82                  {
83                      throw new MessagingException(CoreMessages.cannotCopyStreamPayload(message.getPayload().getClass().getName()), event);
84                  }
85                  eventToRoute = OptimizedRequestContext.criticalSetEvent(event);
86              }
87              else
88              {
89                  eventToRoute = event;
90              }
91  
92              if (outboundRouter.isMatch(eventToRoute.getMessage()))
93              {
94                  matchfound = true;
95                  result = outboundRouter.process(event);
96                  if (!isMatchAll())
97                  {
98                      return result;
99                  }
100             }
101         }
102 
103         if (!matchfound && defaultRoute != null)
104         {
105             if (logger.isDebugEnabled())
106             {
107                 logger.debug("Message did not match any routers on: " + session.getFlowConstruct().getName()
108                              + " invoking catch all strategy");
109             }
110             return processDefaultRoute(event);
111         }
112         else if (!matchfound)
113         {
114             logger.warn("Message did not match any routers on: "
115                         + session.getFlowConstruct().getName()
116                         + " and there is no catch all strategy configured on this router.  Disposing message "
117                         + message);
118         }
119         return event;
120     }
121     
122     protected MuleEvent processDefaultRoute(MuleEvent event) throws MuleException
123     {
124         return defaultRoute.process(event);
125     }
126 
127     public boolean isMatchAll()
128     {
129         return matchAll;
130     }
131 
132     public void setMatchAll(boolean matchAll)
133     {
134         this.matchAll = matchAll;
135     }
136 
137     public void addRoute(MatchableMessageProcessor matchable)
138     {
139         matchableRoutes.add(matchable);
140     }
141 
142     public void removeRoute(MatchableMessageProcessor matchable)
143     {
144         matchableRoutes.remove(matchable);
145     }
146 
147     public void setDefaultRoute(MessageProcessor defaultRoute)
148     {
149         this.defaultRoute = defaultRoute;
150     }
151 
152     public List<MatchableMessageProcessor> getRoutes()
153     {
154         return matchableRoutes;
155     }
156 
157     public MessageProcessor getDefaultRoute()
158     {
159         return defaultRoute;
160     }
161 
162     public void initialise() throws InitialisationException
163     {
164         for (MatchableMessageProcessor route : matchableRoutes)
165         {
166             if (route instanceof Initialisable)
167             {
168                 ((Initialisable) route).initialise();
169             }
170         }
171     }
172 
173     public void dispose()
174     {
175         for (MatchableMessageProcessor route : matchableRoutes)
176         {
177             if (route instanceof Disposable)
178             {
179                 ((Disposable) route).dispose();
180             }
181         }
182     }
183 
184 }