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.service;
8   
9   import org.mule.api.MuleEvent;
10  import org.mule.api.MuleException;
11  import org.mule.api.construct.FlowConstructAware;
12  import org.mule.api.endpoint.InboundEndpoint;
13  import org.mule.api.lifecycle.Disposable;
14  import org.mule.api.lifecycle.Initialisable;
15  import org.mule.api.lifecycle.InitialisationException;
16  import org.mule.api.lifecycle.Startable;
17  import org.mule.api.lifecycle.Stoppable;
18  import org.mule.api.processor.InterceptingMessageProcessor;
19  import org.mule.api.processor.MessageProcessor;
20  import org.mule.api.routing.RouterStatisticsRecorder;
21  import org.mule.api.source.MessageSource;
22  import org.mule.management.stats.RouterStatistics;
23  import org.mule.processor.AbstractInterceptingMessageProcessor;
24  import org.mule.processor.StopFurtherMessageProcessingMessageProcessor;
25  import org.mule.processor.chain.DefaultMessageProcessorChainBuilder;
26  import org.mule.routing.AbstractCatchAllStrategy;
27  import org.mule.routing.MessageFilter;
28  import org.mule.source.StartableCompositeMessageSource;
29  import org.mule.util.StringMessageUtils;
30  
31  import java.util.ArrayList;
32  import java.util.LinkedList;
33  import java.util.List;
34  
35  /**
36   * Extension of {@link StartableCompositeMessageSource} which adds message processors between the composite
37   * source and the target listener
38   */
39  public class ServiceCompositeMessageSource extends StartableCompositeMessageSource implements Initialisable, RouterStatisticsRecorder
40  {
41      protected List<MessageProcessor> processors = new LinkedList<MessageProcessor>();
42      protected RouterStatistics statistics;
43      protected List<InboundEndpoint> endpoints = new ArrayList<InboundEndpoint>();
44      protected MessageProcessor catchAllStrategy;
45      private final InterceptingMessageProcessor internalCatchAllStrategy = new InternalCatchAllMessageProcessor();
46  
47      public ServiceCompositeMessageSource()
48      {
49          statistics = new RouterStatistics(RouterStatistics.TYPE_INBOUND);
50      }
51  
52      @Override
53      public void initialise() throws InitialisationException
54      {
55          super.initialise();
56          if (catchAllStrategy != null)
57          {
58              for (MessageProcessor processor : processors)
59              {
60                  if (processor instanceof MessageFilter
61                      && ((MessageFilter) processor).getUnacceptedMessageProcessor() == null)
62                  {
63                      ((MessageFilter) processor).setUnacceptedMessageProcessor(catchAllStrategy);
64                  }
65              }
66          }
67  
68          try
69          {
70              createMessageProcessorChain();
71          }
72          catch (MuleException e)
73          {
74              throw new InitialisationException(e, this);
75          }
76  
77          for (MessageProcessor processor : processors)
78          {
79              if (processor instanceof FlowConstructAware)
80              {
81                  ((FlowConstructAware) processor).setFlowConstruct(flowConstruct);
82              }
83          }
84          for (MessageProcessor processor : processors)
85          {
86              if (processor instanceof Initialisable)
87              {
88                  ((Initialisable) processor).initialise();
89              }
90          }
91      }
92  
93      @Override
94      public void dispose()
95      {
96          for (MessageProcessor processor : processors)
97          {
98              if (processor instanceof Disposable)
99              {
100                 ((Disposable) processor).dispose();
101             }
102         }
103         super.dispose();
104     }
105 
106     protected void createMessageProcessorChain() throws MuleException
107     {
108         DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder(flowConstruct);
109         builder.chain(processors);
110         builder.chain(new StopFurtherMessageProcessingMessageProcessor());
111         // Stats
112         builder.chain(new AbstractInterceptingMessageProcessor()
113         {
114             public MuleEvent process(MuleEvent event) throws MuleException
115             {
116                 if (getRouterStatistics().isEnabled())
117                 {
118                     getRouterStatistics().incrementRoutedMessage(event.getEndpoint());
119                 }
120                 return processNext(event);
121             }
122         });
123         builder.chain(listener);
124         listener = builder.build();
125     }
126 
127     @Override
128     public void start() throws MuleException
129     {
130         for (MessageProcessor processor : processors)
131         {
132             if (processor instanceof Startable)
133             {
134                 ((Startable) processor).start();
135             }
136         }
137         super.start();
138     }
139 
140     @Override
141     public void stop() throws MuleException
142     {
143         super.stop();
144         for (MessageProcessor processor : processors)
145         {
146             if (processor instanceof Stoppable)
147             {
148                 ((Stoppable) processor).stop();
149             }
150         }
151     }
152 
153     public void setMessageProcessors(List<MessageProcessor> processors)
154     {
155         this.processors = processors;
156     }
157 
158     public void addMessageProcessor(MessageProcessor processor)
159     {
160         this.processors.add(processor);
161     }
162 
163     @Override
164     public void addSource(MessageSource source) throws MuleException
165     {
166         super.addSource(source);
167         if (source instanceof InboundEndpoint)
168         {
169             endpoints.add((InboundEndpoint) source);
170         }
171     }
172 
173     @Override
174     public void removeSource(MessageSource source) throws MuleException
175     {
176         super.removeSource(source);
177         if (source instanceof InboundEndpoint)
178         {
179             endpoints.remove(source);
180         }
181     }
182 
183     @Override
184     public void setMessageSources(List<MessageSource> sources) throws MuleException
185     {
186         this.endpoints.clear();
187         super.setMessageSources(sources);
188     }
189 
190     public List<InboundEndpoint> getEndpoints()
191     {
192         return endpoints;
193     }
194 
195     public List<MessageProcessor> getMessageProcessors()
196     {
197         return processors;
198     }
199 
200     public RouterStatistics getRouterStatistics()
201     {
202         return statistics;
203     }
204 
205     public void setRouterStatistics(RouterStatistics statistics)
206     {
207         this.statistics = statistics;
208     }
209 
210 
211     public InboundEndpoint getEndpoint(String name)
212     {
213         for (InboundEndpoint endpoint : endpoints)
214         {
215             if (endpoint.getName().equals(name))
216             {
217                 return endpoint;
218             }
219         }
220         return null;
221     }
222 
223     public void setCatchAllStrategy(MessageProcessor catchAllStrategy)
224     {
225         if (catchAllStrategy instanceof AbstractCatchAllStrategy)
226         {
227             ((AbstractCatchAllStrategy) catchAllStrategy).setRouterStatistics(statistics);
228         }
229         this.catchAllStrategy = catchAllStrategy;
230         this.internalCatchAllStrategy.setListener(catchAllStrategy);
231     }
232 
233     public MessageProcessor getCatchAllStrategy()
234     {
235         return catchAllStrategy;
236     }
237 
238     class InternalCatchAllMessageProcessor extends AbstractInterceptingMessageProcessor
239     {
240         public MuleEvent process(MuleEvent event) throws MuleException
241         {
242             if (getRouterStatistics().isEnabled())
243             {
244                 getRouterStatistics().incrementNoRoutedMessage();
245             }
246             if (next != null)
247             {
248                 if (logger.isDebugEnabled())
249                 {
250                     logger.debug("Message did not match any routers on: "
251                                  + event.getFlowConstruct().getName() + " - invoking catch all strategy");
252                 }
253                 if (getRouterStatistics().isEnabled())
254                 {
255                     getRouterStatistics().incrementCaughtMessage();
256                 }
257                 return processNext(event);
258             }
259             else
260             {
261                 logger.warn("Message did not match any routers on: "
262                             + event.getFlowConstruct().getName()
263                             + " and there is no catch all strategy configured on this router.  Disposing message: "
264                             + event);
265                 if (logger.isDebugEnabled())
266                 {
267                     try
268                     {
269                         logger.warn("Message fragment is: "
270                                     + StringMessageUtils.truncate(event.getMessageAsString(), 100, true));
271                     }
272                     catch (MuleException e)
273                     {
274                         // ignore
275                     }
276                 }
277                 return null;
278             }
279         }
280     }
281 
282 }