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.outbound;
8   
9   import org.mule.api.MuleEvent;
10  import org.mule.api.MuleException;
11  import org.mule.api.MuleMessage;
12  import org.mule.api.endpoint.EndpointException;
13  import org.mule.api.endpoint.EndpointURI;
14  import org.mule.api.endpoint.ImmutableEndpoint;
15  import org.mule.api.endpoint.OutboundEndpoint;
16  import org.mule.api.expression.ExpressionManager;
17  import org.mule.api.lifecycle.InitialisationException;
18  import org.mule.api.processor.MessageProcessor;
19  import org.mule.api.routing.CouldNotRouteOutboundMessageException;
20  import org.mule.api.routing.RoutePathNotFoundException;
21  import org.mule.api.routing.RoutingException;
22  import org.mule.api.routing.TransformingMatchable;
23  import org.mule.api.routing.filter.Filter;
24  import org.mule.api.transformer.Transformer;
25  import org.mule.config.i18n.CoreMessages;
26  import org.mule.endpoint.DynamicURIOutboundEndpoint;
27  import org.mule.endpoint.MuleEndpointURI;
28  import org.mule.util.TemplateParser;
29  
30  import java.util.HashMap;
31  import java.util.LinkedList;
32  import java.util.List;
33  import java.util.Map;
34  
35  /**
36   * <code>FilteringRouter</code> is a router that accepts events based on a filter
37   * set.
38   */
39  
40  public class FilteringOutboundRouter extends AbstractOutboundRouter implements TransformingMatchable
41  {
42      protected ExpressionManager expressionManager;
43  
44      private List<Transformer> transformers = new LinkedList<Transformer>();
45  
46      private Filter filter;
47  
48      private boolean useTemplates = true;
49      
50      // We used Square templates as they can exist as part of an URI.
51      private TemplateParser parser = TemplateParser.createSquareBracesStyleParser();
52  
53      @Override
54      public void initialise() throws InitialisationException
55      {
56          super.initialise();
57          expressionManager = muleContext.getExpressionManager();
58      }
59  
60      @Override
61      public MuleEvent route(MuleEvent event) throws RoutingException
62      {
63          MuleEvent result;
64  
65          MuleMessage message = event.getMessage();
66  
67          if (routes == null || routes.size() == 0)
68          {
69              throw new RoutePathNotFoundException(CoreMessages.noEndpointsForRouter(), event, null);
70          }
71  
72          MessageProcessor ep = getRoute(0, event);
73  
74          try
75          {
76              result = sendRequest(event, message, ep, true);
77          }
78          catch (RoutingException e)
79          {
80              throw e;
81          }
82          catch (MuleException e)
83          {
84              throw new CouldNotRouteOutboundMessageException(event, ep, e);
85          }
86          return result;
87      }
88  
89      public Filter getFilter()
90      {
91          return filter;
92      }
93  
94      public void setFilter(Filter filter)
95      {
96          this.filter = filter;
97      }
98  
99      public boolean isMatch(MuleMessage message) throws MuleException
100     {
101         if (getFilter() == null)
102         {
103             return true;
104         }
105         
106         message.applyTransformers(null, transformers);
107         
108         return getFilter().accept(message);
109     }
110 
111     public List<Transformer> getTransformers()
112     {
113         return transformers;
114     }
115 
116     public void setTransformers(List<Transformer> transformers)
117     {
118         this.transformers = transformers;
119     }
120 
121     @Override
122     public synchronized void addRoute(MessageProcessor target) throws MuleException
123     {
124         if (!useTemplates)
125         {
126             if (target instanceof ImmutableEndpoint)
127             {
128                 ImmutableEndpoint endpoint = (ImmutableEndpoint) target;
129                 if (parser.isContainsTemplate(endpoint.getEndpointURI().toString()))
130                 {
131                     useTemplates = true;
132                 }
133             }
134         }
135         super.addRoute(target);
136     }
137 
138     /**
139      * Will Return the target at the given index and will resolve any template tags
140      * on the Endpoint URI if necessary
141      * 
142      * @param index the index of the endpoint to get
143      * @param event the current event. This is required if template matching is
144      *            being used
145      * @return the endpoint at the index, with any template tags resolved
146      * @throws CouldNotRouteOutboundMessageException if the template causs the
147      *             endpoint to become illegal or malformed
148      */
149     public MessageProcessor getRoute(int index, MuleEvent event) throws CouldNotRouteOutboundMessageException
150     {
151         if (!useTemplates)
152         {
153             return routes.get(index);
154         }
155         else
156         {
157             MuleMessage message = event.getMessage();
158             MessageProcessor mp = routes.get(index);
159             if (!(mp instanceof ImmutableEndpoint))
160             {
161                 return routes.get(index);
162             }
163             OutboundEndpoint ep = (OutboundEndpoint) mp;
164             String uri = ep.getAddress();
165 
166             if (logger.isDebugEnabled())
167             {
168                 logger.debug("Uri before parsing is: " + uri);
169             }
170 
171             Map<String, Object> props = new HashMap<String, Object>();
172             // Also add the endpoint properties so that users can set fallback values
173             // when the property is not set on the event
174             props.putAll(ep.getProperties());
175             for (String propertyKey : message.getOutboundPropertyNames())
176             {
177                 Object value = message.getOutboundProperty(propertyKey);
178                 props.put(propertyKey, value);
179             }
180 
181             propagateMagicProperties(message, message);
182 
183             if (!parser.isContainsTemplate(uri))
184             {
185                 logger.debug("Uri does not contain template(s)");
186                 return ep;
187             }
188             else
189             {
190 
191                 String newUriString = parser.parse(props, uri);
192                 if (parser.isContainsTemplate(newUriString))
193                 {
194                     newUriString = this.getMuleContext().getExpressionManager().parse(newUriString, message, true);
195                 }
196                 if (logger.isDebugEnabled())
197                 {
198                     logger.debug("Uri after parsing is: " + uri);
199                 }
200                 try
201                 {
202                     EndpointURI newUri = new MuleEndpointURI(newUriString, muleContext);
203                     EndpointURI endpointURI = ep.getEndpointURI();
204                     if (endpointURI != null && !newUri.getScheme().equalsIgnoreCase(endpointURI.getScheme()))
205                     {
206                         throw new CouldNotRouteOutboundMessageException(
207                             CoreMessages.schemeCannotChangeForRouter(ep.getEndpointURI().getScheme(),
208                                 newUri.getScheme()), event, ep);
209                     }
210                     newUri.initialise();
211 
212                     return new DynamicURIOutboundEndpoint(ep, newUri);
213                 }
214                 catch (EndpointException e)
215                 {
216                     throw new CouldNotRouteOutboundMessageException(
217                         CoreMessages.templateCausedMalformedEndpoint(uri, newUriString), event, ep, e);
218                 }
219                 catch (InitialisationException e)
220                 {
221                     throw new CouldNotRouteOutboundMessageException(
222                         CoreMessages.templateCausedMalformedEndpoint(uri, newUriString), event, ep, e);
223                 }
224             }
225         }
226     }
227 
228     public boolean isUseTemplates()
229     {
230         return useTemplates;
231     }
232 
233     public void setUseTemplates(boolean useTemplates)
234     {
235         this.useTemplates = useTemplates;
236     }
237     
238     public boolean isTransformBeforeMatch()
239     {
240         return !transformers.isEmpty();
241     }
242 
243 }