1
2
3
4
5
6
7
8
9
10
11 package org.mule.component;
12
13 import org.mule.DefaultMuleEventContext;
14 import org.mule.RequestContext;
15 import org.mule.api.DefaultMuleException;
16 import org.mule.api.MuleContext;
17 import org.mule.api.MuleEvent;
18 import org.mule.api.MuleEventContext;
19 import org.mule.api.MuleException;
20 import org.mule.api.component.InterfaceBinding;
21 import org.mule.api.component.JavaComponent;
22 import org.mule.api.component.LifecycleAdapter;
23 import org.mule.api.construct.FlowConstruct;
24 import org.mule.api.lifecycle.Disposable;
25 import org.mule.api.lifecycle.Initialisable;
26 import org.mule.api.lifecycle.InitialisationException;
27 import org.mule.api.lifecycle.Startable;
28 import org.mule.api.lifecycle.Stoppable;
29 import org.mule.api.model.EntryPointResolverSet;
30 import org.mule.config.i18n.CoreMessages;
31 import org.mule.config.i18n.MessageFactory;
32 import org.mule.model.resolvers.LegacyEntryPointResolverSet;
33 import org.mule.model.resolvers.NoSatisfiableMethodsException;
34 import org.mule.model.resolvers.TooManySatisfiableMethodsException;
35 import org.mule.registry.JSR250ValidatorProcessor;
36 import org.mule.util.ClassUtils;
37 import org.mule.util.annotation.AnnotationMetaData;
38 import org.mule.util.annotation.AnnotationUtils;
39
40 import java.lang.reflect.InvocationTargetException;
41 import java.lang.reflect.Method;
42 import java.lang.reflect.Proxy;
43 import java.util.HashMap;
44 import java.util.List;
45 import java.util.Map;
46
47 import javax.annotation.PostConstruct;
48 import javax.annotation.PreDestroy;
49
50 import org.apache.commons.logging.Log;
51 import org.apache.commons.logging.LogFactory;
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69 public class DefaultComponentLifecycleAdapter implements LifecycleAdapter
70 {
71
72
73
74 protected static final Log logger = LogFactory.getLog(DefaultComponentLifecycleAdapter.class);
75
76 protected Object componentObject;
77
78 protected JavaComponent component;
79 protected EntryPointResolverSet entryPointResolver;
80 protected FlowConstruct flowConstruct;
81
82 protected boolean isInitialisable = false;
83 protected boolean isStartable = false;
84 protected boolean isStoppable = false;
85 protected boolean isDisposable = false;
86
87 protected Method initMethod;
88 protected Method disposeMethod;
89
90 private boolean started = false;
91 private boolean disposed = false;
92
93 protected MuleContext muleContext;
94
95 public DefaultComponentLifecycleAdapter(Object componentObject,
96 JavaComponent component,
97 FlowConstruct flowConstruct,
98 MuleContext muleContext) throws MuleException
99 {
100 if (muleContext == null)
101 {
102 throw new IllegalStateException("No muleContext provided");
103 }
104 if (componentObject == null)
105 {
106 throw new IllegalArgumentException("POJO Service cannot be null");
107 }
108
109 if (entryPointResolver == null)
110 {
111 entryPointResolver = new LegacyEntryPointResolverSet();
112 }
113 this.componentObject = componentObject;
114 this.component = component;
115 this.flowConstruct = flowConstruct;
116
117
118 this.muleContext = muleContext;
119 setLifecycleFlags();
120 configureBinding();
121 }
122
123 public DefaultComponentLifecycleAdapter(Object componentObject,
124 JavaComponent component,
125 FlowConstruct flowConstruct,
126 EntryPointResolverSet entryPointResolver, MuleContext muleContext) throws MuleException
127 {
128
129 this(componentObject, component, flowConstruct, muleContext);
130 this.entryPointResolver = entryPointResolver;
131 }
132
133 protected void setLifecycleFlags()
134 {
135 Object object = componentObject;
136 initMethod = findInitMethod(object);
137 disposeMethod = findDisposeMethod(object);
138 isInitialisable = initMethod!=null;
139 isDisposable = disposeMethod!=null;
140 isStartable = Startable.class.isInstance(object);
141 isStoppable = Stoppable.class.isInstance(object);
142 }
143
144 protected Method findInitMethod(Object object)
145 {
146 if(object instanceof Initialisable)
147 {
148 try
149 {
150 return object.getClass().getMethod(Initialisable.PHASE_NAME);
151 }
152 catch (NoSuchMethodException e)
153 {
154
155 }
156 }
157
158 List<AnnotationMetaData> metaData = AnnotationUtils.getMethodAnnotations(object.getClass(), PostConstruct.class);
159 if(metaData.size()==0)
160 {
161 return null;
162 }
163 else if(metaData.size() > 1)
164 {
165 throw new IllegalArgumentException(CoreMessages.objectHasMoreThanOnePostConstructAnnotation(object.getClass()).getMessage());
166 }
167 else
168 {
169 Method m = (Method) metaData.get(0).getMember();
170 new JSR250ValidatorProcessor().validateLifecycleMethod(m);
171 return m;
172 }
173 }
174
175 protected Method findDisposeMethod(Object object)
176 {
177 if(object instanceof Disposable)
178 {
179 try
180 {
181 return object.getClass().getMethod(Disposable.PHASE_NAME);
182 }
183 catch (NoSuchMethodException e)
184 {
185
186 }
187 }
188
189 List<AnnotationMetaData> metaData = AnnotationUtils.getMethodAnnotations(object.getClass(), PreDestroy.class);
190 if(metaData.size()==0)
191 {
192 return null;
193 }
194 else if(metaData.size() > 1)
195 {
196 throw new IllegalArgumentException(CoreMessages.objectHasMoreThanOnePreDestroyAnnotation(object.getClass()).getMessage());
197 }
198 else
199 {
200 Method m = (Method) metaData.get(0).getMember();
201 new JSR250ValidatorProcessor().validateLifecycleMethod(m);
202 return m;
203 }
204 }
205
206
207
208
209
210
211
212
213 public void initialise() throws InitialisationException
214 {
215 if (isInitialisable)
216 {
217 try
218 {
219 initMethod.invoke(componentObject);
220 }
221 catch (IllegalAccessException e)
222 {
223 throw new InitialisationException(e, this);
224 }
225 catch (InvocationTargetException e)
226 {
227 throw new InitialisationException(e.getTargetException(), this);
228 }
229 }
230 }
231
232
233
234
235
236
237 public void start() throws MuleException
238 {
239 if (isStartable)
240 {
241 try
242 {
243 ((Startable) componentObject).start();
244 started = true;
245 }
246 catch (Exception e)
247 {
248 throw new DefaultMuleException(CoreMessages.failedToStart("Service: "
249 + flowConstruct.getName()), e);
250 }
251 }
252 else
253 {
254 started = true;
255 }
256 }
257
258
259
260
261
262
263 public void stop() throws MuleException
264 {
265 if (isStoppable)
266 {
267 try
268 {
269 ((Stoppable) componentObject).stop();
270 started = false;
271 }
272 catch (Exception e)
273 {
274 throw new DefaultMuleException(CoreMessages.failedToStop("Service: "
275 + flowConstruct.getName()), e);
276 }
277 }
278 else
279 {
280 started = false;
281 }
282 }
283
284
285
286
287
288
289 public void dispose()
290 {
291 try
292 {
293 if (isDisposable)
294 {
295
296 Object o = componentObject;
297 if (o != null)
298 {
299 try
300 {
301 disposeMethod.invoke(o);
302 }
303 catch (InvocationTargetException e)
304 {
305
306 throw e.getTargetException();
307 }
308 }
309 }
310 componentObject = null;
311
312 }
313 catch (Throwable e)
314 {
315 logger.error("failed to dispose: " + flowConstruct.getName(), e);
316 }
317 disposed = true;
318 }
319
320
321
322
323 public boolean isStarted()
324 {
325 return started;
326 }
327
328
329
330
331 public boolean isDisposed()
332 {
333 return disposed;
334 }
335
336 public Object invoke(MuleEvent event) throws MuleException
337 {
338
339 MuleEventContext eventContext = new DefaultMuleEventContext(event);
340 Object result;
341 try
342 {
343 if (componentObject == null)
344 {
345 throw new ComponentException(MessageFactory.createStaticMessage("componentObject is null"), RequestContext.getEvent(), component);
346 }
347
348 if (component.getEntryPointResolverSet() != null)
349 {
350 result = component.getEntryPointResolverSet().invoke(componentObject, eventContext);
351 }
352 else
353 {
354 result = entryPointResolver.invoke(componentObject, eventContext);
355 }
356 }
357 catch (Exception e)
358 {
359 throw new ComponentException(RequestContext.getEvent(), component, e);
360 }
361
362 return result;
363 }
364
365 protected void configureBinding() throws MuleException
366 {
367
368
369 if (component.getInterfaceBindings() != null)
370 {
371 Map<Class<?>, Object> bindings = new HashMap<Class<?>, Object>();
372 for (InterfaceBinding interfaceBinding : component.getInterfaceBindings())
373 {
374 Object proxy = bindings.get(interfaceBinding.getInterface());
375
376 if (proxy == null)
377 {
378
379
380
381
382 proxy = interfaceBinding.createProxy(componentObject);
383 bindings.put(interfaceBinding.getInterface(), proxy);
384
385
386 Method setterMethod;
387
388 List methods = ClassUtils.getSatisfiableMethods(componentObject.getClass(),
389 new Class[]{interfaceBinding.getInterface()}, true, false, null);
390 if (methods.size() == 1)
391 {
392 setterMethod = (Method) methods.get(0);
393 }
394 else if (methods.size() > 1)
395 {
396 throw new TooManySatisfiableMethodsException(componentObject.getClass(),
397 new Class[]{interfaceBinding.getInterface()});
398 }
399 else
400 {
401 throw new NoSatisfiableMethodsException(componentObject.getClass(),
402 new Class[]{interfaceBinding.getInterface()});
403 }
404
405 try
406 {
407 setterMethod.invoke(componentObject, proxy);
408 }
409 catch (Exception e)
410 {
411 throw new InitialisationException(CoreMessages.failedToSetProxyOnService(interfaceBinding,
412 componentObject.getClass()), e, this);
413 }
414 }
415 else
416 {
417 BindingInvocationHandler handler = (BindingInvocationHandler) Proxy.getInvocationHandler(proxy);
418 handler.addRouterForInterface(interfaceBinding);
419 }
420 }
421 }
422 }
423 }