1
2
3
4
5
6
7
8
9
10
11 package org.mule.component;
12
13 import org.mule.DefaultMuleEvent;
14 import org.mule.DefaultMuleMessage;
15 import org.mule.OptimizedRequestContext;
16 import org.mule.VoidResult;
17 import org.mule.api.MuleContext;
18 import org.mule.api.MuleEvent;
19 import org.mule.api.MuleException;
20 import org.mule.api.MuleMessage;
21 import org.mule.api.component.Component;
22 import org.mule.api.construct.FlowConstruct;
23 import org.mule.api.context.MuleContextAware;
24 import org.mule.api.context.notification.ServerNotificationHandler;
25 import org.mule.api.interceptor.Interceptor;
26 import org.mule.api.lifecycle.Initialisable;
27 import org.mule.api.lifecycle.InitialisationException;
28 import org.mule.api.lifecycle.Lifecycle;
29 import org.mule.api.lifecycle.LifecycleException;
30 import org.mule.api.processor.MessageProcessor;
31 import org.mule.api.processor.MessageProcessorChain;
32 import org.mule.api.transformer.Transformer;
33 import org.mule.config.i18n.CoreMessages;
34 import org.mule.config.i18n.MessageFactory;
35 import org.mule.context.notification.ComponentMessageNotification;
36 import org.mule.context.notification.OptimisedNotificationHandler;
37 import org.mule.management.stats.ComponentStatistics;
38 import org.mule.processor.chain.DefaultMessageProcessorChainBuilder;
39 import org.mule.transformer.TransformerTemplate;
40 import org.mule.transport.NullPayload;
41
42 import java.util.ArrayList;
43 import java.util.Collections;
44 import java.util.List;
45
46 import org.apache.commons.logging.Log;
47 import org.apache.commons.logging.LogFactory;
48
49
50
51
52 public abstract class AbstractComponent implements Component, MuleContextAware, Lifecycle
53 {
54
55
56
57
58 protected final Log logger = LogFactory.getLog(this.getClass());
59
60 protected FlowConstruct flowConstruct;
61 protected ComponentStatistics statistics = null;
62 protected ServerNotificationHandler notificationHandler;
63 protected List<Interceptor> interceptors = new ArrayList<Interceptor>();
64 protected MessageProcessorChain interceptorChain;
65 protected MuleContext muleContext;
66
67 public void setMuleContext(MuleContext context)
68 {
69 this.muleContext = context;
70 }
71
72 public List<Interceptor> getInterceptors()
73 {
74 return interceptors;
75 }
76
77 public void setInterceptors(List<Interceptor> interceptors)
78 {
79 this.interceptors = interceptors;
80 }
81
82 public AbstractComponent()
83 {
84 statistics = new ComponentStatistics();
85 }
86
87 private MuleEvent invokeInternal(MuleEvent event) throws MuleException
88 {
89
90 OptimizedRequestContext.unsafeSetEvent(event);
91
92 if (logger.isTraceEnabled())
93 {
94 logger.trace(String.format("Invoking %s component for service %s",
95 this.getClass().getName(), flowConstruct.getName()));
96 }
97
98 if (!flowConstruct.getLifecycleState().isStarted() || flowConstruct.getLifecycleState().isStopping())
99 {
100 throw new LifecycleException(CoreMessages.isStopped(flowConstruct.getName()), this);
101 }
102
103
104 try
105 {
106 fireComponentNotification(event.getMessage(), ComponentMessageNotification.COMPONENT_PRE_INVOKE);
107
108 long startTime = 0;
109 if (statistics.isEnabled())
110 {
111 startTime = System.currentTimeMillis();
112 }
113
114 Object result = doInvoke(event);
115
116 if (statistics.isEnabled())
117 {
118 statistics.addExecutionTime(System.currentTimeMillis() - startTime);
119 }
120
121 MuleEvent resultEvent = createResultEvent(event, result);
122
123 resultEvent.setStopFurtherProcessing(event.isStopFurtherProcessing());
124 fireComponentNotification(resultEvent.getMessage(), ComponentMessageNotification.COMPONENT_POST_INVOKE);
125
126 return resultEvent;
127 }
128 catch (MuleException me)
129 {
130 throw me;
131 }
132 catch (Exception e)
133 {
134 throw new ComponentException(CoreMessages.failedToInvoke(this.toString()), event,
135 this, e);
136 }
137 }
138
139 public MuleEvent process(MuleEvent event) throws MuleException
140 {
141 if (interceptorChain == null)
142 {
143 return invokeInternal(event);
144 }
145 else
146 {
147 return interceptorChain.process(event);
148 }
149 }
150
151 protected MuleEvent createResultEvent(MuleEvent event, Object result) throws MuleException
152 {
153 if (result instanceof MuleMessage)
154 {
155 return new DefaultMuleEvent((MuleMessage) result, event);
156 }
157 else if (result instanceof VoidResult)
158 {
159 return event;
160 }
161 else if (result != null)
162 {
163 event.getMessage().applyTransformers(
164 event, Collections.<Transformer>singletonList(new TransformerTemplate(
165 new TransformerTemplate.OverwitePayloadCallback(result))));
166 return event;
167 }
168 else
169 {
170 return new DefaultMuleEvent(new DefaultMuleMessage(NullPayload.getInstance(), muleContext), event);
171 }
172 }
173
174 protected abstract Object doInvoke(MuleEvent event) throws Exception;
175
176 @Override
177 public String toString()
178 {
179 StringBuilder buf = new StringBuilder(this.getClass().getName());
180
181 if (flowConstruct != null)
182 {
183 buf.append(" component for: ").append(flowConstruct.toString());
184 }
185 else
186 {
187 buf.append(" no component");
188 }
189
190 return buf.toString();
191 }
192
193 public void release()
194 {
195
196 }
197
198 public ComponentStatistics getStatistics()
199 {
200 return statistics;
201 }
202
203 public void setFlowConstruct(FlowConstruct flowConstruct)
204 {
205 this.flowConstruct = flowConstruct;
206
207 }
208
209 public FlowConstruct getFlowConstruct()
210 {
211 return flowConstruct;
212 }
213
214 public final void initialise() throws InitialisationException
215 {
216 if (logger.isInfoEnabled())
217 {
218 logger.info("Initialising: " + this);
219 }
220 if (flowConstruct == null)
221 {
222 throw new InitialisationException(
223 MessageFactory.createStaticMessage("Component has not been initialized properly, no service."),
224 this);
225 }
226
227 DefaultMessageProcessorChainBuilder chainBuilder = new DefaultMessageProcessorChainBuilder(flowConstruct);
228 for (Interceptor interceptor : interceptors)
229 {
230 chainBuilder.chain(interceptor);
231 }
232 chainBuilder.chain(new MessageProcessor()
233 {
234 public MuleEvent process(MuleEvent event) throws MuleException
235 {
236 return invokeInternal(event);
237 }
238 });
239
240 try
241 {
242 interceptorChain = chainBuilder.build();
243 if (interceptorChain instanceof Initialisable)
244 {
245 ((Initialisable) interceptorChain).initialise();
246 }
247 }
248 catch (MuleException e)
249 {
250 throw new InitialisationException(e, this);
251 }
252
253 doInitialise();
254 }
255
256 protected void doInitialise() throws InitialisationException
257 {
258
259 }
260
261 public void dispose()
262 {
263 if (flowConstruct.getLifecycleState().isDisposed())
264 {
265 return;
266 }
267
268 try
269 {
270
271 if (flowConstruct.getLifecycleState().isStarted())
272 {
273 stop();
274 }
275 }
276 catch (MuleException e)
277 {
278 logger.error(CoreMessages.failedToStop(toString()));
279 }
280 try
281 {
282 doDispose();
283
284 }
285 catch (Exception e)
286 {
287 logger.warn(CoreMessages.failedToDispose(toString()), e);
288 }
289 }
290
291 protected void doDispose()
292 {
293
294 }
295
296 public void stop() throws MuleException
297 {
298 if (flowConstruct.getLifecycleState().isStopped())
299 {
300 return;
301 }
302 if (logger.isInfoEnabled())
303 {
304 logger.info("Stopping: " + this);
305 }
306 doStop();
307 }
308
309 protected void doStart() throws MuleException
310 {
311
312 }
313
314 public void start() throws MuleException
315 {
316 if (flowConstruct.getLifecycleState().isStarted())
317 {
318 return;
319 }
320
321 if (logger.isInfoEnabled())
322 {
323 logger.info("Starting: " + this);
324 }
325 notificationHandler = new OptimisedNotificationHandler(muleContext.getNotificationManager(),
326 ComponentMessageNotification.class);
327 doStart();
328 }
329
330 protected void doStop() throws MuleException
331 {
332
333 }
334
335 protected void fireComponentNotification(MuleMessage message, int action)
336 {
337 if (notificationHandler != null && notificationHandler.isNotificationEnabled(ComponentMessageNotification.class))
338 {
339 notificationHandler.fireNotification(new ComponentMessageNotification(message, this, flowConstruct, action));
340 }
341 }
342
343 }