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.DefaultMuleEvent;
14  import org.mule.OptimizedRequestContext;
15  import org.mule.api.MuleEvent;
16  import org.mule.api.MuleException;
17  import org.mule.api.construct.FlowConstruct;
18  import org.mule.api.endpoint.OutboundEndpoint;
19  import org.mule.api.lifecycle.Disposable;
20  import org.mule.api.processor.InterceptingMessageProcessor;
21  import org.mule.api.processor.MessageProcessor;
22  import org.mule.api.processor.MessageProcessorBuilder;
23  import org.mule.construct.SimpleFlowConstruct;
24  import org.mule.processor.AbstractInterceptingMessageProcessor;
25  import org.mule.processor.NullMessageProcessor;
26  
27  import java.util.ArrayList;
28  import java.util.List;
29  
30  /**
31   * <p>
32   * Constructs a chain of {@link MessageProcessor}s and wraps the invocation of the
33   * chain in a composite MessageProcessor. Both MessageProcessors and
34   * InterceptingMessageProcessor's can be chained together arbitrarily in a single
35   * chain. InterceptingMessageProcessors simply intercept the next MessageProcessor in
36   * the chain. When other non-intercepting MessageProcessors are used an adapter is
37   * used internally to chain the MessageProcessor with the next in the chain.
38   * </p>
39   * <p>
40   * The MessageProcessor instance that this builder builds can be nested in other
41   * chains as required.
42   * </p>
43   */
44  public class InterceptingChainMessageProcessorBuilder implements MessageProcessorBuilder
45  {
46  
47      protected List processors = new ArrayList();
48      protected String name;
49      protected FlowConstruct flowConstruct;
50  
51      public InterceptingChainMessageProcessorBuilder()
52      {
53          // empty
54      }
55      
56      public InterceptingChainMessageProcessorBuilder(FlowConstruct flowConstruct)
57      {
58          this.flowConstruct = flowConstruct;
59      }
60      
61      public MessageProcessor build() throws MuleException
62      {
63          if (processors.isEmpty())
64          {
65              return new NullMessageProcessor();
66          }
67  
68          InterceptingMessageProcessor first = createInterceptingMessageProcessor(initializeMessageProcessor(processors.get(0)));
69          MessageProcessor composite = new InterceptingChainCompositeMessageProcessor(first, processors, name);
70          InterceptingMessageProcessor current = first;
71  
72          for (int i = 1; i < processors.size(); i++)
73          {
74              InterceptingMessageProcessor mp = createInterceptingMessageProcessor(initializeMessageProcessor(processors.get(i)));
75              current.setListener(mp);
76              current = mp;
77          }
78          return composite;
79      }
80  
81      // Argument is of type Object because it could be a MessageProcessor or a MessageProcessorBuilder
82      protected MessageProcessor initializeMessageProcessor(Object processor) throws MuleException
83      {
84          if (processor instanceof MessageProcessorBuilder)
85          {
86              return ((MessageProcessorBuilder) processor).build();
87          }
88          else
89          {
90              return (MessageProcessor) processor;
91          }
92      }
93      
94      public void setName(String name)
95      {
96          this.name = name;
97      }
98  
99      private InterceptingMessageProcessor createInterceptingMessageProcessor(MessageProcessor processor)
100     {
101         if (processor instanceof InterceptingMessageProcessor)
102         {
103             return (InterceptingMessageProcessor) processor;
104         }
105         else
106         {
107             return new InterceptingMessageProcessorAdapter(processor);
108         }
109     }
110 
111     public InterceptingChainMessageProcessorBuilder chain(MessageProcessor... processors)
112     {
113         for (MessageProcessor messageProcessor : processors)
114         {
115             this.processors.add(messageProcessor);
116         }
117         return this;
118     }
119 
120     public InterceptingChainMessageProcessorBuilder chain(List<MessageProcessor> processors)
121     {
122         if (processors != null)
123         {
124             this.processors.addAll(processors);
125         }
126         return this;
127     }
128 
129     public InterceptingChainMessageProcessorBuilder chain(MessageProcessorBuilder... builders)
130     {
131         for (MessageProcessorBuilder messageProcessorBuilder : builders)
132         {
133             this.processors.add(messageProcessorBuilder);
134         }
135         return this;
136     }
137 
138     public InterceptingChainMessageProcessorBuilder chainBefore(MessageProcessor processor)
139     {
140         this.processors.add(0, processor);
141         return this;
142     }
143 
144     public InterceptingChainMessageProcessorBuilder chainBefore(MessageProcessorBuilder builder)
145     {
146         this.processors.add(0, builder);
147         return this;
148     }
149     
150     @Override
151     public String toString()
152     {
153         if (name != null)
154         {
155             return "InterceptingChainMessageProcessorBuilder '" + name + "'";
156         }
157         else
158         {
159             return super.toString();
160         }
161     }
162 
163     class InterceptingMessageProcessorAdapter extends AbstractInterceptingMessageProcessor implements Disposable
164     {
165         private MessageProcessor delegate;
166 
167         public InterceptingMessageProcessorAdapter(MessageProcessor mp)
168         {
169             this.delegate = mp;
170         }
171 
172         public MuleEvent process(MuleEvent event) throws MuleException
173         {
174             if (logger.isTraceEnabled())
175             {
176                 logger.trace("Invoking adapted MessageProcessor '" + delegate.getClass().getName() + "'");
177             }
178             // If the next message processor is an outbound router then create
179             // outbound event
180             if (delegate instanceof OutboundEndpoint)
181             {
182                 event = new DefaultMuleEvent(event.getMessage(), (OutboundEndpoint) delegate,
183                     event.getSession());
184             }
185             MuleEvent delegateResult = delegate.process(event);
186             if (delegateResult != null)
187             {
188                 return processNext(delegateResult);
189             }
190             else if (event.getFlowConstruct() instanceof SimpleFlowConstruct)
191             {
192                 return processNext(OptimizedRequestContext.criticalSetEvent(event));
193             }
194             else
195             {
196                 return null;
197             }
198         }
199 
200         public void setNext(MessageProcessor next)
201         {
202             this.next = next;
203         }
204 
205         public void dispose()
206         {
207             this.delegate = null;
208         }
209 
210         @Override
211         public String toString()
212         {
213             return "InterceptingMessageProcessorAdapter [ target = '" + delegate.getClass().getName() + "' ]";
214         }
215     }
216 
217 }