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.processor.chain;
8   
9   import org.mule.OptimizedRequestContext;
10  import org.mule.api.MuleEvent;
11  import org.mule.api.MuleException;
12  import org.mule.api.component.Component;
13  import org.mule.api.construct.FlowConstruct;
14  import org.mule.api.endpoint.OutboundEndpoint;
15  import org.mule.api.processor.MessageProcessor;
16  import org.mule.api.processor.MessageProcessorChain;
17  import org.mule.api.transformer.Transformer;
18  import org.mule.construct.SimpleFlowConstruct;
19  import org.mule.context.notification.MessageProcessorNotification;
20  import org.mule.routing.MessageFilter;
21  import org.mule.routing.requestreply.ReplyToMessageProcessor;
22  
23  import java.util.Arrays;
24  import java.util.Iterator;
25  import java.util.List;
26  
27  public class DefaultMessageProcessorChain extends AbstractMessageProcessorChain
28  {
29  
30      protected DefaultMessageProcessorChain(List<MessageProcessor> processors)
31      {   
32          super(null, processors);
33      }
34  
35      protected DefaultMessageProcessorChain(MessageProcessor... processors)
36      {
37          super(null, Arrays.asList(processors));
38      }
39  
40      protected DefaultMessageProcessorChain(String name, List<MessageProcessor> processors)
41      {
42          super(name, processors);
43      }
44  
45      protected DefaultMessageProcessorChain(String name, MessageProcessor... processors)
46      {
47          super(name, Arrays.asList(processors));
48      }
49  
50      public static MessageProcessorChain from(MessageProcessor messageProcessor)
51      {
52          return new DefaultMessageProcessorChain(messageProcessor);
53      }
54  
55      public static MessageProcessorChain from(MessageProcessor... messageProcessors) throws MuleException
56      {
57          return new DefaultMessageProcessorChainBuilder().chain(messageProcessors).build();
58      }
59  
60      public static MessageProcessorChain from(List<MessageProcessor> messageProcessors) throws MuleException
61      {
62          return new DefaultMessageProcessorChainBuilder().chain(messageProcessors).build();
63      }
64      
65      protected MuleEvent doProcess(MuleEvent event) throws MuleException
66      {
67          FlowConstruct flowConstruct = event.getFlowConstruct();
68          MuleEvent currentEvent = event;
69          MuleEvent resultEvent;
70          MuleEvent copy = null;
71          Iterator<MessageProcessor> processorIterator = processors.iterator();
72          MessageProcessor processor = null;
73          if (processorIterator.hasNext())
74          {
75              processor = processorIterator.next();
76          }
77          boolean resultWasNull = false;
78          while (processor != null)
79          {
80              MessageProcessor nextProcessor = null;
81              if (processorIterator.hasNext())
82              {
83                  nextProcessor = processorIterator.next();
84              }
85              fireNotification(event.getFlowConstruct(), event, processor,
86                  MessageProcessorNotification.MESSAGE_PROCESSOR_PRE_INVOKE);
87  
88              if (flowConstruct instanceof SimpleFlowConstruct && nextProcessor != null
89                  && processorMayReturnNull(processor))
90              {
91                  copy = OptimizedRequestContext.criticalSetEvent(currentEvent);
92              }
93  
94              resultEvent = processor.process(currentEvent);
95              if (resultWasNull && processor instanceof ReplyToMessageProcessor)
96              {
97                  // reply-to processing should not resurrect a dead event
98                  resultEvent = null;
99              }
100 
101             fireNotification(event.getFlowConstruct(), resultEvent, processor,
102                 MessageProcessorNotification.MESSAGE_PROCESSOR_POST_INVOKE);
103 
104             if (resultEvent != null)
105             {
106                 resultWasNull = false;
107                 currentEvent = resultEvent;
108             }
109             else if (flowConstruct instanceof SimpleFlowConstruct && nextProcessor != null)
110             {
111                 resultWasNull = true;
112                 // // In a flow when a MessageProcessor returns null the next
113                 // processor acts as an implicit
114                 // // branch receiving a copy of the message used for previous
115                 // MessageProcessor
116                 if (copy != null)
117                 {
118                     currentEvent = copy;
119                 }
120                 else
121                 {
122                     // this should not happen
123                     currentEvent = OptimizedRequestContext.criticalSetEvent(currentEvent);
124                 }
125             }
126             else
127             {
128                 // But in a service we don't do any implicit branching.
129                 return null;
130             }
131             processor = nextProcessor;
132         }
133         return currentEvent;
134     }
135 
136     protected boolean processorMayReturnNull(MessageProcessor processor)
137     {
138         if (processor instanceof OutboundEndpoint)
139         {
140             return  !((OutboundEndpoint) processor).getExchangePattern().hasResponse();
141         }
142         else if (processor instanceof Component || processor instanceof Transformer
143                  || processor instanceof MessageFilter)
144         {
145             return false;
146         }
147         else
148         {
149             return true;
150         }
151     }
152 
153 }