View Javadoc

1   /*
2    * $Id$
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.processor.builder;
12  
13  import org.mule.api.MuleContext;
14  import org.mule.api.MuleEvent;
15  import org.mule.api.MuleException;
16  import org.mule.api.construct.FlowConstruct;
17  import org.mule.api.construct.FlowConstructAware;
18  import org.mule.api.context.MuleContextAware;
19  import org.mule.api.lifecycle.Disposable;
20  import org.mule.api.lifecycle.Initialisable;
21  import org.mule.api.lifecycle.InitialisationException;
22  import org.mule.api.lifecycle.Lifecycle;
23  import org.mule.api.lifecycle.Startable;
24  import org.mule.api.lifecycle.Stoppable;
25  import org.mule.api.processor.MessageProcessor;
26  import org.mule.api.processor.MessageProcessorBuilder;
27  import org.mule.processor.NullMessageProcessor;
28  import org.mule.util.StringUtils;
29  
30  import java.util.ArrayList;
31  import java.util.Collection;
32  import java.util.Iterator;
33  import java.util.List;
34  
35  import org.apache.commons.logging.Log;
36  import org.apache.commons.logging.LogFactory;
37  
38  /**
39   * <p>
40   * Constructs a chain of {@link MessageProcessor}s and wraps the invocation of the
41   * chain in a composite MessageProcessor. Both MessageProcessors and
42   * InterceptingMessageProcessor's can be chained together arbitrarily in a single
43   * chain. InterceptingMessageProcessors simply intercept the next MessageProcessor in
44   * the chain. When other non-intercepting MessageProcessors are used an adapter is
45   * used internally to chain the MessageProcessor with the next in the chain.
46   * </p>
47   * <p>
48   * The MessageProcessor instance that this builder builds can be nested in other
49   * chains as required.
50   * </p>
51   */
52  public class IteratingListMessageProcessorBuilder implements MessageProcessorBuilder
53  {
54  
55      protected List processors = new ArrayList();
56      protected String name;
57  
58      public MessageProcessor build() throws MuleException
59      {
60          if (processors.isEmpty())
61          {
62              return new NullMessageProcessor();
63          }
64          return new IteratingListCompositeMessageProcessor(processors, name);
65      }
66  
67      public void setName(String name)
68      {
69          this.name = name;
70      }
71  
72      public IteratingListMessageProcessorBuilder add(MessageProcessor... processors)
73      {
74          for (MessageProcessor messageProcessor : processors)
75          {
76              this.processors.add(messageProcessor);
77          }
78          return this;
79      }
80  
81      public IteratingListMessageProcessorBuilder add(MessageProcessorBuilder... builders)
82      {
83          for (MessageProcessorBuilder builder : builders)
84          {
85              this.processors.add(builder);
86          }
87          return this;
88      }
89  
90      public IteratingListMessageProcessorBuilder InterceptingChainMessageProcessorBuilder(Collection<MessageProcessor> processors)
91      {
92          if (processors != null)
93          {
94              this.processors.addAll(processors);
95          }
96          return this;
97      }
98  
99      public IteratingListMessageProcessorBuilder addBefore(MessageProcessor processor)
100     {
101         this.processors.add(0, processor);
102         return this;
103     }
104 
105     public IteratingListMessageProcessorBuilder addBefore(MessageProcessorBuilder builder)
106     {
107         this.processors.add(0, builder);
108         return this;
109     }
110 
111     @Override
112     public String toString()
113     {
114         if (name != null)
115         {
116             return "IteratingListMessageProcessorBuilder '" + name + "'";
117         }
118         else
119         {
120             return super.toString();
121         }
122     }
123 
124     /**
125      * Builder needs to return a composite rather than the first MessageProcessor in
126      * the chain. This is so that if this chain is nested in another chain the next
127      * MessageProcessor in the parent chain is not injected into the first in the
128      * nested chain.
129      */
130     static class IteratingListCompositeMessageProcessor
131         implements MessageProcessor, Lifecycle, FlowConstructAware, MuleContextAware
132     {
133         private Log log;
134         private String name;
135         private List<MessageProcessor> list = new ArrayList<MessageProcessor>();
136 
137         public IteratingListCompositeMessageProcessor(List processors, String name) throws MuleException
138         {
139             this.name = name;
140             for (Object object : list)
141             {
142                 list.add(getMessageProcessor(object));
143             }
144             log = LogFactory.getLog(IteratingListCompositeMessageProcessor.class);
145         }
146 
147         private MessageProcessor getMessageProcessor(Object processor) throws MuleException
148         {
149             if (processor instanceof MessageProcessor)
150             {
151                 return (MessageProcessor) processor;
152             }
153             else if (processor instanceof MessageProcessorBuilder)
154             {
155                 return ((MessageProcessorBuilder) processor).build();
156             }
157             else
158             {
159                 throw new IllegalArgumentException(
160                     "MessageProcessorBuilder should only have MessageProcessor's or MessageProcessorBuilder's configured");
161             }
162         }
163 
164         public MuleEvent process(MuleEvent event) throws MuleException
165         {
166             if (log.isDebugEnabled())
167             {
168                 log.debug("Invoking " + this + " with event " + event);
169             }
170             MuleEvent result = event;
171             for (MessageProcessor processor : list)
172             {
173                 result = processor.process(result);
174             }
175             return result;
176         }
177 
178         public void initialise() throws InitialisationException
179         {
180             for (MessageProcessor processor : list)
181             {
182                 if (processor instanceof Initialisable)
183                 {
184                     ((Initialisable) processor).initialise();
185                 }
186             }
187         }
188 
189         public void start() throws MuleException
190         {
191             for (MessageProcessor processor : list)
192             {
193                 if (processor instanceof Startable)
194                 {
195                     ((Startable) processor).start();
196                 }
197             }
198         }
199 
200         public void stop() throws MuleException
201         {
202             for (MessageProcessor processor : list)
203             {
204                 if (processor instanceof Stoppable)
205                 {
206                     ((Stoppable) processor).stop();
207                 }
208             }
209         }
210 
211         public void dispose()
212         {
213             for (MessageProcessor processor : list)
214             {
215                 if (processor instanceof Disposable)
216                 {
217                     ((Disposable) processor).dispose();
218                 }
219             }
220         }
221 
222         public void setFlowConstruct(FlowConstruct flowConstruct)
223         {
224             for (MessageProcessor processor : list)
225             {
226                 if (processor instanceof FlowConstructAware)
227                 {
228                     ((FlowConstructAware) processor).setFlowConstruct(flowConstruct);
229                 }
230             }
231         }
232 
233         public void setMuleContext(MuleContext muleContext)
234         {
235             for (MessageProcessor processor : list)
236             {
237                 if (processor instanceof MuleContextAware)
238                 {
239                     ((MuleContextAware) processor).setMuleContext(muleContext);
240                 }
241             }
242         }
243 
244         @Override
245         public String toString()
246         {
247             StringBuffer string = new StringBuffer();
248             string.append("IteratingListCompositeMessageProcessor ");
249             if (name != null)
250             {
251                 string.append(" '" + name + "' ");
252             }
253             
254             Iterator<MessageProcessor> mpIterator = list.iterator();
255             if (mpIterator.hasNext())
256             {
257                 string.append("\n[ ");
258                 while (mpIterator.hasNext())
259                 {
260                     MessageProcessor mp = mpIterator.next();
261                     string.append("\n  " + StringUtils.replace(mp.toString(), "\n", "\n  "));
262                     if (mpIterator.hasNext())
263                     {
264                         string.append(", ");
265                     }
266                 }
267                 string.append("\n]");
268             }
269 
270             return string.toString();
271         }
272     }
273 }