View Javadoc

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