View Javadoc

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