1
2
3
4
5
6
7 package org.mule.transport;
8
9 import org.mule.api.MuleException;
10 import org.mule.api.MuleMessage;
11 import org.mule.api.config.MuleConfiguration;
12 import org.mule.api.context.WorkManager;
13 import org.mule.api.endpoint.ImmutableEndpoint;
14 import org.mule.api.lifecycle.CreateException;
15 import org.mule.api.lifecycle.InitialisationException;
16 import org.mule.api.lifecycle.LifecycleCallback;
17 import org.mule.api.lifecycle.LifecycleState;
18 import org.mule.api.lifecycle.LifecycleStateEnabled;
19 import org.mule.api.retry.RetryContext;
20 import org.mule.api.retry.RetryPolicyTemplate;
21 import org.mule.api.transport.Connectable;
22 import org.mule.api.transport.Connector;
23 import org.mule.api.transport.MuleMessageFactory;
24 import org.mule.config.i18n.CoreMessages;
25 import org.mule.config.i18n.Message;
26 import org.mule.config.i18n.MessageFactory;
27 import org.mule.context.notification.ConnectionNotification;
28 import org.mule.util.ClassUtils;
29
30 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;
31
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34
35
36
37
38 public abstract class AbstractTransportMessageHandler<O> implements Connectable, LifecycleStateEnabled
39 {
40 protected transient Log logger = LogFactory.getLog(getClass());
41
42 protected ImmutableEndpoint endpoint;
43 protected final AbstractConnector connector;
44 protected RetryPolicyTemplate retryTemplate;
45 protected MuleMessageFactory muleMessageFactory = null;
46
47 protected ConnectableLifecycleManager<O> lifecycleManager;
48
49 protected final AtomicBoolean connected = new AtomicBoolean(false);
50
51 public AbstractTransportMessageHandler(ImmutableEndpoint endpoint)
52 {
53 this.endpoint = endpoint;
54 this.connector = (AbstractConnector) endpoint.getConnector();
55 this.lifecycleManager = createLifecycleManager();
56 }
57
58 protected abstract ConnectableLifecycleManager<O> createLifecycleManager();
59
60 public LifecycleState getLifecycleState()
61 {
62 return lifecycleManager.getState();
63 }
64
65 protected void disposeAndLogException()
66 {
67 try
68 {
69 dispose();
70 }
71 catch (Throwable t)
72 {
73 logger.error("Could not dispose of the message dispatcher!", t);
74 }
75 }
76
77 public boolean validate()
78 {
79
80 return !getLifecycleState().isDisposed();
81 }
82
83 public void activate()
84 {
85
86 }
87
88 public void passivate()
89 {
90
91 }
92
93 public void initialise() throws InitialisationException
94 {
95 try
96 {
97 lifecycleManager.fireInitialisePhase(new LifecycleCallback<O>()
98 {
99 public void onTransition(String phaseName, O object) throws MuleException
100 {
101 initializeRetryPolicy();
102 initializeMessageFactory();
103 doInitialise();
104 }
105 });
106 }
107 catch (InitialisationException e)
108 {
109 throw e;
110 }
111 catch (MuleException e)
112 {
113 throw new InitialisationException(e, this);
114 }
115
116 }
117
118 protected void initializeRetryPolicy()
119 {
120 if (endpoint.getRetryPolicyTemplate() != null)
121 {
122 retryTemplate = endpoint.getRetryPolicyTemplate();
123 }
124 else
125 {
126 retryTemplate = connector.getRetryPolicyTemplate();
127 }
128 }
129
130
131
132
133
134 protected void initializeMessageFactory() throws InitialisationException
135 {
136 try
137 {
138 muleMessageFactory = connector.getMuleMessageFactory();
139 }
140 catch (CreateException ce)
141 {
142 Message message = MessageFactory.createStaticMessage(ce.getMessage());
143 throw new InitialisationException(message, ce, this);
144 }
145 }
146
147
148
149
150 public synchronized void dispose()
151 {
152 try
153 {
154 if (isStarted())
155 {
156 stop();
157 }
158 if (isConnected())
159 {
160 disconnect();
161 }
162 }
163 catch (Exception e)
164 {
165 logger.warn(e.getMessage(), e);
166 }
167
168 try
169 {
170 lifecycleManager.fireDisposePhase(new LifecycleCallback<O>()
171 {
172 public void onTransition(String phaseName, O object) throws MuleException
173 {
174 doDispose();
175 }
176 });
177 }
178 catch (MuleException e)
179 {
180 logger.warn(e.getMessage(), e);
181 }
182 }
183
184 public Connector getConnector()
185 {
186 return connector;
187 }
188
189 public ImmutableEndpoint getEndpoint()
190 {
191 return endpoint;
192 }
193
194 public final synchronized void connect() throws Exception
195 {
196
197
198 if (connected.get())
199 {
200 return;
201 }
202
203 if (getLifecycleState().isDisposed())
204 {
205 throw new IllegalStateException(
206 "Requester/dispatcher has been disposed; cannot connect to resource:" + this);
207 }
208
209 if (logger.isDebugEnabled())
210 {
211 logger.debug("Connecting: " + this);
212 }
213
214 doConnect();
215 connected.set(true);
216
217 if (logger.isDebugEnabled())
218 {
219 logger.debug("Connected: " + getConnectionDescription());
220 }
221 }
222
223 public RetryContext validateConnection(RetryContext retryContext)
224 {
225 retryContext.setOk();
226 return retryContext;
227 }
228
229 public final synchronized void disconnect() throws Exception
230 {
231 if (isStarted())
232 {
233 stop();
234 }
235
236 if (logger.isDebugEnabled())
237 {
238 logger.debug("Disconnecting: " + this);
239 }
240
241 doDisconnect();
242 connected.set(false);
243
244 if (logger.isDebugEnabled())
245 {
246 logger.debug("Disconnected: " + this);
247 }
248 connector.fireNotification(new ConnectionNotification(this, getConnectEventId(endpoint),
249 ConnectionNotification.CONNECTION_DISCONNECTED));
250 }
251
252 protected String getConnectEventId(ImmutableEndpoint endpoint)
253 {
254 return connector.getName() + ".dispatcher(" + endpoint.getEndpointURI().getUri() + ")";
255 }
256
257 public final boolean isConnected()
258 {
259 return connected.get();
260 }
261
262 protected boolean isDoThreading()
263 {
264 return connector.getDispatcherThreadingProfile().isDoThreading();
265 }
266
267
268
269
270 public String getConnectionDescription()
271 {
272 return "endpoint.outbound." + endpoint.getEndpointURI().toString();
273 }
274
275
276
277
278
279
280
281
282
283
284
285 public final void start() throws MuleException
286 {
287 if (isStarted() || isStarting())
288 {
289 return;
290 }
291
292 if (!isConnected())
293 {
294 try
295 {
296 connect();
297 }
298 catch (MuleException me)
299 {
300 throw me;
301 }
302 catch (Exception e)
303 {
304 throw new ConnectException(e, this);
305 }
306 }
307
308 lifecycleManager.fireStartPhase(new LifecycleCallback<O>()
309 {
310 public void onTransition(String phaseName, O object) throws MuleException
311 {
312 doStart();
313 }
314 });
315 }
316
317 public final void stop() throws MuleException
318 {
319 lifecycleManager.fireStopPhase(new LifecycleCallback<O>()
320 {
321 public void onTransition(String phaseName, O object) throws MuleException
322 {
323 try
324 {
325 doStop();
326 }
327 catch (MuleException e)
328 {
329 logger.error(e.getMessage(), e);
330 }
331 }
332 });
333
334 }
335
336 protected void doInitialise() throws InitialisationException
337 {
338
339 }
340
341 protected void doDispose()
342 {
343
344 }
345
346 protected void doConnect() throws Exception
347 {
348
349 }
350
351 protected void doDisconnect() throws Exception
352 {
353
354 }
355
356 protected void doStart() throws MuleException
357 {
358
359 }
360
361 protected void doStop() throws MuleException
362 {
363
364 }
365
366 @Override
367 public String toString()
368 {
369 final StringBuffer sb = new StringBuffer(80);
370 sb.append(ClassUtils.getSimpleName(this.getClass()));
371 sb.append("{this=").append(Integer.toHexString(System.identityHashCode(this)));
372 sb.append(", endpoint=").append(endpoint.getEndpointURI());
373 sb.append(", disposed=").append(getLifecycleState().isDisposed());
374 sb.append('}');
375 return sb.toString();
376 }
377
378
379
380 public void setEndpoint(ImmutableEndpoint endpoint)
381 {
382 if (endpoint == null)
383 {
384 throw new IllegalArgumentException("Endpoint cannot be null");
385 }
386 this.endpoint = endpoint;
387 }
388
389 abstract protected WorkManager getWorkManager() throws MuleException;
390
391 public boolean isStarted()
392 {
393 return getLifecycleState().isStarted();
394 }
395
396 public boolean isStarting()
397 {
398 return getLifecycleState().isStarting();
399 }
400
401 public boolean isStopped()
402 {
403 return getLifecycleState().isStopped();
404 }
405
406 public boolean isStopping()
407 {
408 return getLifecycleState().isStopping();
409 }
410
411
412
413
414
415
416 protected MuleMessageFactory createMuleMessageFactory() throws CreateException
417 {
418 return connector.createMuleMessageFactory();
419 }
420
421
422
423
424
425
426 public MuleMessage createMuleMessage(Object transportMessage, MuleMessage previousMessage,
427 String encoding) throws MuleException
428 {
429 try
430 {
431 return muleMessageFactory.create(transportMessage, previousMessage, encoding);
432 }
433 catch (Exception e)
434 {
435 throw new CreateException(CoreMessages.failedToCreate("MuleMessage"), e);
436 }
437 }
438
439
440
441
442
443 public MuleMessage createMuleMessage(Object transportMessage, String encoding) throws MuleException
444 {
445 try
446 {
447 return muleMessageFactory.create(transportMessage, encoding);
448 }
449 catch (Exception e)
450 {
451 throw new CreateException(CoreMessages.failedToCreate("MuleMessage"), e, this);
452 }
453 }
454
455
456
457
458
459
460
461 public MuleMessage createMuleMessage(Object transportMessage) throws MuleException
462 {
463 String encoding = endpoint.getMuleContext().getConfiguration().getDefaultEncoding();
464 return createMuleMessage(transportMessage, encoding);
465 }
466
467
468
469
470
471
472 protected MuleMessage createNullMuleMessage() throws MuleException
473 {
474 return createMuleMessage(null);
475 }
476 }