View Javadoc

1   /*
2    * $Id: AbstractMessageProcessorChain.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.processor.chain;
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.MessageProcessorChain;
27  import org.mule.api.processor.policy.AroundPolicy;
28  import org.mule.api.processor.policy.Policies;
29  import org.mule.api.processor.policy.PolicyInvocation;
30  import org.mule.processor.AbstractInterceptingMessageProcessor;
31  import org.mule.util.StringUtils;
32  
33  import java.util.Iterator;
34  import java.util.List;
35  
36  import org.apache.commons.logging.Log;
37  import org.apache.commons.logging.LogFactory;
38  
39  /**
40   * Builder needs to return a composite rather than the first MessageProcessor in the chain. This is so that if
41   * this chain is nested in another chain the next MessageProcessor in the parent chain is not injected into
42   * the first in the nested chain.
43   */
44  public abstract class AbstractMessageProcessorChain extends AbstractInterceptingMessageProcessor
45                                                      implements MessageProcessorChain, Lifecycle, FlowConstructAware, MuleContextAware
46  {
47      protected final transient Log log = LogFactory.getLog(getClass());
48      protected String name;
49      protected List<MessageProcessor> processors;
50      private final Policies policies = new Policies(this);
51  
52      public AbstractMessageProcessorChain(String name, List<MessageProcessor> processors)
53      {
54          this.name = name;
55          this.processors = processors;
56      }
57  
58      public MuleEvent process(MuleEvent event) throws MuleException
59      {
60          if (log.isDebugEnabled())
61          {
62              log.debug(String.format("Invoking %s with event %s", this, event));
63          }
64          if (event == null)
65          {
66              return null;
67          }
68  
69          final List<AroundPolicy> activePolicies = policies.list();
70          MuleEvent result;
71          if (!activePolicies.isEmpty())
72          {
73              // if there's a policy, adapt, so it can call through to the doProcess() method
74              // TODO I hate to do this, and there are no method delegates in java.
75              // This doProcess() must be abstracted into some chain processor which has the logic,
76              // and have the chain handle the plumbing only
77              PolicyInvocation invocation = new PolicyInvocation(event, activePolicies, new MessageProcessor()
78              {
79                  public MuleEvent process(MuleEvent event) throws MuleException
80                  {
81                      return doProcess(event);
82                  }
83              });
84              final AroundPolicy entryPoint = activePolicies.get(0);
85              result = entryPoint.invoke(invocation);
86          }
87          else
88          {
89              // direct invocation
90              result = doProcess(event);
91          }
92          return processNext(result);
93      }
94  
95      protected abstract MuleEvent doProcess(MuleEvent event) throws MuleException;
96  
97      public void initialise() throws InitialisationException
98      {
99          for (MessageProcessor processor : processors)
100         {
101             // MULE-5002 TODO review MP Lifecycle
102             if (processor instanceof Initialisable /* && !(processor instanceof Transformer) */)
103             {
104                 ((Initialisable) processor).initialise();
105             }
106         }
107     }
108 
109     public void start() throws MuleException
110     {
111         for (MessageProcessor processor : processors)
112         {
113             if (processor instanceof Startable)
114             {
115                 ((Startable) processor).start();
116             }
117         }
118     }
119 
120     public void stop() throws MuleException
121     {
122         for (MessageProcessor processor : processors)
123         {
124             if (processor instanceof Stoppable)
125             {
126                 ((Stoppable) processor).stop();
127             }
128         }
129     }
130 
131     public void dispose()
132     {
133         for (MessageProcessor processor : processors)
134         {
135             if (processor instanceof Disposable)
136             {
137                 ((Disposable) processor).dispose();
138             }
139         }
140         processors.clear();
141     }
142 
143     public void setFlowConstruct(FlowConstruct flowConstruct)
144     {
145         for (MessageProcessor processor : processors)
146         {
147             if (processor instanceof FlowConstructAware)
148             {
149                 ((FlowConstructAware) processor).setFlowConstruct(flowConstruct);
150             }
151         }
152     }
153 
154     public void setMuleContext(MuleContext context)
155     {
156         for (MessageProcessor processor : processors)
157         {
158             if (processor instanceof MuleContextAware)
159             {
160                 ((MuleContextAware) processor).setMuleContext(context);
161             }
162         }
163     }
164 
165     public String getName()
166     {
167         return name;
168     }
169 
170     @Override
171     public String toString()
172     {
173         StringBuilder string = new StringBuilder();
174         string.append(getClass().getSimpleName());
175         if (StringUtils.isNotBlank(name))
176         {
177             string.append(String.format(" '%s' ", name));
178         }
179 
180         Iterator<MessageProcessor> mpIterator = processors.iterator();
181 
182         final String nl = String.format("%n");
183 
184         for (AroundPolicy policy : policies.list())
185         {
186             string.append(String.format("%n  -- policy [%s]: %s", policy.getName(), policy));
187         }
188 
189         // TODO have it print the nested structure with indents increasing for nested MPCs
190         if (mpIterator.hasNext())
191         {
192             string.append(String.format("%n[ "));
193             while (mpIterator.hasNext())
194             {
195                 MessageProcessor mp = mpIterator.next();
196                 final String indented = StringUtils.replace(mp.toString(), nl, String.format("%n  "));
197                 string.append(String.format("%n  %s", indented));
198                 if (mpIterator.hasNext())
199                 {
200                     string.append(", ");
201                 }
202             }
203             string.append(String.format("%n]"));
204         }
205 
206         return string.toString();
207     }
208 
209     public List<MessageProcessor> getMessageProcessors()
210     {
211         return processors;
212     }
213 
214     public Policies getPolicies()
215     {
216         return policies;
217     }
218 }