1
2
3
4
5
6
7
8
9
10
11 package org.mule.transport;
12
13 import org.mule.MessageExchangePattern;
14 import org.mule.api.MessagingException;
15 import org.mule.api.MuleContext;
16 import org.mule.api.MuleEvent;
17 import org.mule.api.MuleException;
18 import org.mule.api.MuleMessage;
19 import org.mule.api.MuleRuntimeException;
20 import org.mule.api.config.MuleProperties;
21 import org.mule.api.config.ThreadingProfile;
22 import org.mule.api.construct.FlowConstruct;
23 import org.mule.api.context.WorkManager;
24 import org.mule.api.context.WorkManagerSource;
25 import org.mule.api.context.notification.ServerNotification;
26 import org.mule.api.context.notification.ServerNotificationHandler;
27 import org.mule.api.endpoint.EndpointURI;
28 import org.mule.api.endpoint.ImmutableEndpoint;
29 import org.mule.api.endpoint.InboundEndpoint;
30 import org.mule.api.endpoint.OutboundEndpoint;
31 import org.mule.api.lifecycle.CreateException;
32 import org.mule.api.lifecycle.InitialisationException;
33 import org.mule.api.lifecycle.LifecycleCallback;
34 import org.mule.api.lifecycle.LifecycleException;
35 import org.mule.api.lifecycle.LifecycleState;
36 import org.mule.api.processor.MessageProcessor;
37 import org.mule.api.registry.ServiceException;
38 import org.mule.api.registry.ServiceType;
39 import org.mule.api.retry.RetryCallback;
40 import org.mule.api.retry.RetryContext;
41 import org.mule.api.retry.RetryPolicyTemplate;
42 import org.mule.api.transformer.Transformer;
43 import org.mule.api.transport.Connectable;
44 import org.mule.api.transport.Connector;
45 import org.mule.api.transport.ConnectorException;
46 import org.mule.api.transport.DispatchException;
47 import org.mule.api.transport.MessageDispatcher;
48 import org.mule.api.transport.MessageDispatcherFactory;
49 import org.mule.api.transport.MessageReceiver;
50 import org.mule.api.transport.MessageRequester;
51 import org.mule.api.transport.MessageRequesterFactory;
52 import org.mule.api.transport.MuleMessageFactory;
53 import org.mule.api.transport.ReplyToHandler;
54 import org.mule.api.transport.SessionHandler;
55 import org.mule.config.i18n.CoreMessages;
56 import org.mule.config.i18n.MessageFactory;
57 import org.mule.context.notification.ConnectionNotification;
58 import org.mule.context.notification.EndpointMessageNotification;
59 import org.mule.context.notification.OptimisedNotificationHandler;
60 import org.mule.endpoint.outbound.OutboundNotificationMessageProcessor;
61 import org.mule.model.streaming.DelegatingInputStream;
62 import org.mule.processor.LaxAsyncInterceptingMessageProcessor;
63 import org.mule.processor.chain.DefaultMessageProcessorChainBuilder;
64 import org.mule.routing.filters.WildcardFilter;
65 import org.mule.session.SerializeAndEncodeSessionHandler;
66 import org.mule.transformer.TransformerUtils;
67 import org.mule.transport.service.TransportFactory;
68 import org.mule.transport.service.TransportServiceDescriptor;
69 import org.mule.transport.service.TransportServiceException;
70 import org.mule.util.ClassUtils;
71 import org.mule.util.CollectionUtils;
72 import org.mule.util.ObjectNameHelper;
73 import org.mule.util.ObjectUtils;
74 import org.mule.util.StringUtils;
75 import org.mule.util.concurrent.NamedThreadFactory;
76 import org.mule.util.concurrent.ThreadNameHelper;
77
78 import java.io.IOException;
79 import java.io.InputStream;
80 import java.io.OutputStream;
81 import java.text.MessageFormat;
82 import java.util.ArrayList;
83 import java.util.Collections;
84 import java.util.Iterator;
85 import java.util.List;
86 import java.util.Map;
87 import java.util.Properties;
88 import java.util.concurrent.ConcurrentHashMap;
89 import java.util.concurrent.ScheduledExecutorService;
90 import java.util.concurrent.ScheduledThreadPoolExecutor;
91 import java.util.concurrent.ThreadFactory;
92 import java.util.concurrent.TimeUnit;
93 import java.util.concurrent.atomic.AtomicBoolean;
94 import java.util.concurrent.atomic.AtomicReference;
95
96 import javax.resource.spi.work.WorkEvent;
97 import javax.resource.spi.work.WorkListener;
98
99 import org.apache.commons.logging.Log;
100 import org.apache.commons.logging.LogFactory;
101 import org.apache.commons.pool.KeyedPoolableObjectFactory;
102 import org.apache.commons.pool.impl.GenericKeyedObjectPool;
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130 public abstract class AbstractConnector implements Connector, WorkListener
131 {
132
133
134
135 public static final int DEFAULT_NUM_CONCURRENT_TX_RECEIVERS = 4;
136
137 private static final long SCHEDULER_FORCED_SHUTDOWN_TIMEOUT = 5000l;
138
139 public static final String PROPERTY_POLLING_FREQUENCY = "pollingFrequency";
140
141
142
143
144 protected final Log logger = LogFactory.getLog(getClass());
145
146
147
148
149 protected volatile String name;
150
151
152
153
154 protected volatile MessageDispatcherFactory dispatcherFactory;
155
156
157
158
159 protected volatile MessageRequesterFactory requesterFactory;
160
161
162
163
164 protected MuleMessageFactory muleMessageFactory;
165
166
167
168
169 protected volatile ConfigurableKeyedObjectPool dispatchers;
170
171
172
173
174 protected volatile ConfigurableKeyedObjectPoolFactory dispatcherPoolFactory;
175
176
177
178
179 protected final GenericKeyedObjectPool requesters = new GenericKeyedObjectPool();
180
181
182
183
184 protected final Map<Object, MessageReceiver> receivers = new ConcurrentHashMap<Object, MessageReceiver>();
185
186
187
188
189 private volatile ThreadingProfile dispatcherThreadingProfile;
190
191
192
193
194 private volatile ThreadingProfile requesterThreadingProfile;
195
196
197
198
199 private volatile ThreadingProfile receiverThreadingProfile;
200
201
202
203
204 protected volatile boolean createMultipleTransactedReceivers = true;
205
206
207
208
209 protected volatile int numberOfConcurrentTransactedReceivers = DEFAULT_NUM_CONCURRENT_TX_RECEIVERS;
210
211 private RetryPolicyTemplate retryPolicyTemplate;
212
213
214
215
216
217
218 private boolean dynamicNotification = false;
219 private ServerNotificationHandler cachedNotificationHandler;
220
221 private final List<String> supportedProtocols;
222
223
224
225
226 private final AtomicReference<WorkManager> receiverWorkManager = new AtomicReference<WorkManager>();
227
228
229
230
231 private final AtomicReference<WorkManager> dispatcherWorkManager = new AtomicReference<WorkManager>();
232
233
234
235
236 private final AtomicReference<WorkManager> requesterWorkManager = new AtomicReference<WorkManager>();
237
238
239
240
241 private ScheduledExecutorService scheduler;
242
243
244
245
246 protected volatile TransportServiceDescriptor serviceDescriptor;
247
248
249
250
251
252 protected volatile Properties serviceOverrides;
253
254
255
256
257
258 protected volatile SessionHandler sessionHandler = new SerializeAndEncodeSessionHandler();
259
260 protected MuleContext muleContext;
261
262 protected ConnectorLifecycleManager lifecycleManager;
263
264
265 private AtomicBoolean connected = new AtomicBoolean(false);
266 private AtomicBoolean connecting = new AtomicBoolean(false);
267
268
269
270
271
272
273 protected boolean startOnConnect = false;
274
275
276
277
278
279
280
281
282
283 protected boolean initialStateStopped = false;
284
285
286
287 private boolean validateConnections = true;
288
289 public AbstractConnector(MuleContext context)
290 {
291 muleContext = context;
292 lifecycleManager = new ConnectorLifecycleManager(this);
293
294 setDynamicNotification(false);
295 updateCachedNotificationHandler();
296
297
298 supportedProtocols = new ArrayList<String>();
299 supportedProtocols.add(getProtocol().toLowerCase());
300
301
302
303
304
305
306 requesters.setTestOnBorrow(false);
307 requesters.setTestOnReturn(true);
308 }
309
310 @Override
311 public String getName()
312 {
313 return name;
314 }
315
316 @Override
317 public void setName(String newName)
318 {
319 if (newName == null)
320 {
321 throw new IllegalArgumentException(CoreMessages.objectIsNull("Connector name").toString());
322 }
323
324 if (logger.isDebugEnabled())
325 {
326 logger.debug("Set Connector name to: " + newName);
327 }
328
329 name = newName;
330 }
331
332
333
334
335
336 ConnectorLifecycleManager getLifecycleManager()
337 {
338 return lifecycleManager;
339 }
340
341 @Override
342 public LifecycleState getLifecycleState()
343 {
344 return lifecycleManager.getState();
345 }
346
347 @Override
348 public final synchronized void initialise() throws InitialisationException
349 {
350 try
351 {
352 lifecycleManager.fireInitialisePhase(new LifecycleCallback<Connector>()
353 {
354 @Override
355 public void onTransition(String phaseName, Connector object) throws MuleException
356 {
357 if (retryPolicyTemplate == null)
358 {
359 retryPolicyTemplate = (RetryPolicyTemplate) muleContext.getRegistry().lookupObject(
360 MuleProperties.OBJECT_DEFAULT_RETRY_POLICY_TEMPLATE);
361 }
362
363 if (dispatcherPoolFactory == null) {
364 dispatcherPoolFactory = new DefaultConfigurableKeyedObjectPoolFactory();
365 }
366
367 dispatchers = dispatcherPoolFactory.createObjectPool();
368 if (dispatcherFactory != null) {
369 dispatchers.setFactory(getWrappedDispatcherFactory(dispatcherFactory));
370 }
371
372
373 initFromServiceDescriptor();
374
375 configureDispatcherPool();
376 setMaxRequestersActive(getRequesterThreadingProfile().getMaxThreadsActive());
377
378 doInitialise();
379
380 try
381 {
382 initWorkManagers();
383 }
384 catch (MuleException e)
385 {
386 throw new LifecycleException(e, this);
387 }
388 }
389 });
390 }
391 catch (InitialisationException e)
392 {
393 throw e;
394 }
395 catch (LifecycleException e)
396 {
397 throw new InitialisationException(e, this);
398 }
399 catch (MuleException e)
400 {
401 e.printStackTrace();
402 }
403 }
404
405
406 @Override
407 public final synchronized void start() throws MuleException
408 {
409 if (isInitialStateStopped())
410 {
411 logger.info("Connector not started because 'initialStateStopped' is true");
412 return;
413 }
414
415 if (!isConnected())
416 {
417 try
418 {
419
420
421 startOnConnect = true;
422 connect();
423 }
424 catch (MuleException me)
425 {
426 throw me;
427 }
428 catch (Exception e)
429 {
430 throw new ConnectException(e, this);
431 }
432 }
433 else
434 {
435 startAfterConnect();
436 }
437 }
438
439
440 protected synchronized void startAfterConnect() throws MuleException
441 {
442
443 startOnConnect = false;
444
445
446
447
448
449
450
451 if (logger.isInfoEnabled())
452 {
453 logger.info("Starting: " + this);
454 }
455
456 lifecycleManager.fireStartPhase(new LifecycleCallback<Connector>()
457 {
458 @Override
459 public void onTransition(String phaseName, Connector object) throws MuleException
460 {
461 initWorkManagers();
462 scheduler = createScheduler();
463 doStart();
464
465 if (receivers != null)
466 {
467 for (MessageReceiver receiver : receivers.values())
468 {
469 final List<MuleException> errors = new ArrayList<MuleException>();
470 try
471 {
472 if (logger.isDebugEnabled())
473 {
474 logger.debug("Starting receiver on endpoint: "
475 + receiver.getEndpoint().getEndpointURI());
476 }
477 if (receiver.getFlowConstruct().getLifecycleState().isStarted())
478 {
479 receiver.start();
480 }
481 }
482 catch (MuleException e)
483 {
484 logger.error(e);
485 errors.add(e);
486 }
487
488 if (!errors.isEmpty())
489 {
490
491
492
493
494
495 throw errors.get(0);
496 }
497 }
498 }
499 }
500 });
501 }
502
503 @Override
504 public final synchronized void stop() throws MuleException
505 {
506
507
508
509
510
511
512 lifecycleManager.fireStopPhase(new LifecycleCallback<Connector>()
513 {
514 @Override
515 public void onTransition(String phaseName, Connector object) throws MuleException
516 {
517
518 shutdownScheduler();
519
520 doStop();
521
522
523 if (receivers != null)
524 {
525 for (MessageReceiver receiver : receivers.values())
526 {
527 if (logger.isDebugEnabled())
528 {
529 logger.debug("Stopping receiver on endpoint: " + receiver.getEndpoint().getEndpointURI());
530 }
531 receiver.stop();
532 }
533 }
534
535
536
537 disposeWorkManagers();
538
539
540 clearDispatchers();
541 clearRequesters();
542
543
544 scheduler = null;
545 }
546 });
547 }
548
549 @Override
550 public final synchronized void dispose()
551 {
552 try
553 {
554 if (isStarted())
555 {
556 stop();
557 }
558 if (isConnected())
559 {
560 disconnect();
561 }
562 }
563 catch (Exception e)
564 {
565 logger.warn(e.getMessage(), e);
566 }
567
568 try
569 {
570 lifecycleManager.fireDisposePhase(new LifecycleCallback<Connector>()
571 {
572 @Override
573 public void onTransition(String phaseName, Connector object) throws MuleException
574 {
575 doDispose();
576 disposeReceivers();
577 }
578 });
579 }
580 catch (MuleException e)
581 {
582 logger.warn(e.getMessage(), e);
583 }
584 }
585
586 @Override
587 public final boolean isStarted()
588 {
589 return lifecycleManager.getState().isStarted();
590 }
591
592 public final boolean isStarting()
593 {
594 return lifecycleManager.getState().isStarting();
595 }
596
597 public boolean isInitialised()
598 {
599 return lifecycleManager.getState().isInitialised();
600 }
601
602 public boolean isStopped()
603 {
604 return lifecycleManager.getState().isStopped();
605 }
606
607 public boolean isStopping()
608 {
609 return lifecycleManager.getState().isStopping();
610 }
611
612
613
614
615
616
617 protected void configureDispatcherPool()
618 {
619
620
621 int maxDispatchersActive = getDispatcherThreadingProfile().getMaxThreadsActive();
622
623
624
625
626
627
628 if (ThreadingProfile.WHEN_EXHAUSTED_RUN == getDispatcherThreadingProfile().getPoolExhaustedAction())
629 {
630 maxDispatchersActive++;
631 }
632 setMaxDispatchersActive(maxDispatchersActive);
633 }
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648 @Override
649 public MuleMessageFactory createMuleMessageFactory() throws CreateException
650 {
651 try
652 {
653 return serviceDescriptor.createMuleMessageFactory();
654 }
655 catch (TransportServiceException tse)
656 {
657 throw new CreateException(CoreMessages.failedToCreate("MuleMessageFactory"), tse, this);
658 }
659 }
660
661 protected void shutdownScheduler()
662 {
663 if (scheduler != null)
664 {
665
666 scheduler.shutdown();
667 try
668 {
669
670 if (!scheduler.awaitTermination(muleContext.getConfiguration().getShutdownTimeout(),
671 TimeUnit.MILLISECONDS))
672 {
673
674
675 List outstanding = scheduler.shutdownNow();
676
677 if (!scheduler.awaitTermination(SCHEDULER_FORCED_SHUTDOWN_TIMEOUT, TimeUnit.MILLISECONDS))
678 {
679 logger.warn(MessageFormat.format(
680 "Pool {0} did not terminate in time; {1} work items were cancelled.", name,
681 outstanding.isEmpty() ? "No" : Integer.toString(outstanding.size())));
682 }
683 else
684 {
685 if (!outstanding.isEmpty())
686 {
687 logger.warn(MessageFormat.format(
688 "Pool {0} terminated; {1} work items were cancelled.", name,
689 Integer.toString(outstanding.size())));
690 }
691 }
692
693 }
694 }
695 catch (InterruptedException ie)
696 {
697
698 scheduler.shutdownNow();
699
700 Thread.currentThread().interrupt();
701 }
702 finally
703 {
704 scheduler = null;
705 }
706 }
707 }
708
709 protected void initWorkManagers() throws MuleException
710 {
711 if (receiverWorkManager.get() == null)
712 {
713
714 final String threadPrefix = ThreadNameHelper.receiver(muleContext, getName());
715 WorkManager newWorkManager = this.getReceiverThreadingProfile().createWorkManager(
716 threadPrefix, muleContext.getConfiguration().getShutdownTimeout());
717
718 if (receiverWorkManager.compareAndSet(null, newWorkManager))
719 {
720 newWorkManager.start();
721 }
722 }
723 if (dispatcherWorkManager.get() == null)
724 {
725 ThreadingProfile dispatcherThreadingProfile = this.getDispatcherThreadingProfile();
726 if (dispatcherThreadingProfile.getMuleContext() == null)
727 {
728 dispatcherThreadingProfile.setMuleContext(muleContext);
729 }
730
731 final String threadPrefix = ThreadNameHelper.dispatcher(muleContext, getName());
732 WorkManager newWorkManager = dispatcherThreadingProfile.createWorkManager(
733 threadPrefix, muleContext.getConfiguration().getShutdownTimeout());
734
735 if (dispatcherWorkManager.compareAndSet(null, newWorkManager))
736 {
737 newWorkManager.start();
738 }
739 }
740 if (requesterWorkManager.get() == null)
741 {
742 final String threadPrefix = ThreadNameHelper.requester(muleContext, getName());
743 WorkManager newWorkManager = this.getRequesterThreadingProfile().createWorkManager(
744 threadPrefix, muleContext.getConfiguration().getShutdownTimeout());
745
746 if (requesterWorkManager.compareAndSet(null, newWorkManager))
747 {
748 newWorkManager.start();
749 }
750 }
751 }
752
753 protected void disposeWorkManagers()
754 {
755 WorkManager workManager;
756
757 logger.debug("Disposing dispatcher work manager");
758 workManager = dispatcherWorkManager.get();
759 if (workManager != null)
760 {
761 workManager.dispose();
762 }
763 dispatcherWorkManager.set(null);
764
765 logger.debug("Disposing requester work manager");
766 workManager = requesterWorkManager.get();
767 if (workManager != null)
768 {
769 workManager.dispose();
770 }
771 requesterWorkManager.set(null);
772
773 logger.debug("Disposing receiver work manager");
774 workManager = receiverWorkManager.get();
775 if (workManager != null)
776 {
777 workManager.dispose();
778 }
779 receiverWorkManager.set(null);
780 }
781
782 protected void disposeReceivers()
783 {
784 if (receivers != null)
785 {
786 logger.debug("Disposing Receivers");
787
788 for (MessageReceiver receiver : receivers.values())
789 {
790 try
791 {
792 this.destroyReceiver(receiver, receiver.getEndpoint());
793 }
794 catch (Throwable e)
795 {
796
797 logger.error("Failed to destroy receiver: " + receiver, e);
798 }
799 }
800
801 receivers.clear();
802 logger.debug("Receivers Disposed");
803 }
804 }
805
806 protected void clearDispatchers()
807 {
808 if (dispatchers != null)
809 {
810 logger.debug("Clearing Dispatcher pool");
811 synchronized (dispatchers)
812 {
813 dispatchers.clear();
814 }
815 logger.debug("Dispatcher pool cleared");
816 }
817 }
818
819 protected void clearRequesters()
820 {
821 if (requesters != null)
822 {
823 logger.debug("Clearing Requester pool");
824 requesters.clear();
825 logger.debug("Requester pool cleared");
826 }
827 }
828
829 @Override
830 public boolean isDisposed()
831 {
832 return lifecycleManager.getState().isDisposed();
833 }
834
835
836
837
838 @Override
839 public MessageDispatcherFactory getDispatcherFactory()
840 {
841 return dispatcherFactory;
842 }
843
844
845
846
847 @Override
848 public void setDispatcherFactory(MessageDispatcherFactory dispatcherFactory)
849 {
850 KeyedPoolableObjectFactory poolFactory = getWrappedDispatcherFactory(dispatcherFactory);
851
852 if (dispatchers != null) {
853 this.dispatchers.setFactory(poolFactory);
854 }
855
856
857
858 this.dispatcherFactory = dispatcherFactory;
859 }
860
861 private KeyedPoolableObjectFactory getWrappedDispatcherFactory(MessageDispatcherFactory dispatcherFactory)
862 {
863 KeyedPoolableObjectFactory poolFactory;
864 if (dispatcherFactory instanceof KeyedPoolableObjectFactory)
865 {
866 poolFactory = (KeyedPoolableObjectFactory) dispatcherFactory;
867 }
868 else
869 {
870
871 poolFactory = new KeyedPoolMessageDispatcherFactoryAdapter(dispatcherFactory);
872 }
873
874 return poolFactory;
875 }
876
877
878
879
880 @Override
881 public MessageRequesterFactory getRequesterFactory()
882 {
883 return requesterFactory;
884 }
885
886
887
888
889 @Override
890 public void setRequesterFactory(MessageRequesterFactory requesterFactory)
891 {
892 KeyedPoolableObjectFactory poolFactory;
893
894 if (requesterFactory instanceof KeyedPoolableObjectFactory)
895 {
896 poolFactory = (KeyedPoolableObjectFactory) requesterFactory;
897 }
898 else
899 {
900
901 poolFactory = new KeyedPoolMessageRequesterFactoryAdapter(requesterFactory);
902 }
903
904 requesters.setFactory(poolFactory);
905
906
907
908 this.requesterFactory = requesterFactory;
909 }
910
911
912
913
914
915
916
917
918 public MuleMessageFactory getMuleMessageFactory() throws CreateException
919 {
920 if (muleMessageFactory == null)
921 {
922 muleMessageFactory = createMuleMessageFactory();
923 }
924 return muleMessageFactory;
925 }
926
927
928
929
930
931
932
933
934
935
936
937
938
939 public boolean isInitialStateStopped()
940 {
941 return initialStateStopped;
942 }
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959 public void setInitialStateStopped(boolean initialStateStopped)
960 {
961 this.initialStateStopped = initialStateStopped;
962 }
963
964
965
966
967
968
969
970 public int getMaxDispatchersActive()
971 {
972 checkDispatchersInitialised();
973 return this.dispatchers.getMaxActive();
974 }
975
976
977
978
979
980 private void checkDispatchersInitialised()
981 {
982 if (dispatchers == null)
983 {
984 throw new IllegalStateException("Dispatchers pool was not initialised");
985 }
986 }
987
988
989
990
991
992
993
994 public int getMaxTotalDispatchers()
995 {
996 checkDispatchersInitialised();
997 return this.dispatchers.getMaxTotal();
998 }
999
1000
1001
1002
1003
1004
1005
1006 public void setMaxDispatchersActive(int maxActive)
1007 {
1008 checkDispatchersInitialised();
1009 this.dispatchers.setMaxActive(maxActive);
1010
1011 this.dispatchers.setMaxIdle(maxActive);
1012
1013
1014 this.dispatchers.setMaxTotal(20 * maxActive);
1015 }
1016
1017 private MessageDispatcher getDispatcher(OutboundEndpoint endpoint) throws MuleException
1018 {
1019 if (!isStarted())
1020 {
1021 throw new LifecycleException(CoreMessages.lifecycleErrorCannotUseConnector(getName(),
1022 lifecycleManager.getCurrentPhase()), this);
1023 }
1024
1025 if (endpoint == null)
1026 {
1027 throw new IllegalArgumentException("Endpoint must not be null");
1028 }
1029
1030 if (!supportsProtocol(endpoint.getConnector().getProtocol()))
1031 {
1032 throw new IllegalArgumentException(CoreMessages.connectorSchemeIncompatibleWithEndpointScheme(
1033 this.getProtocol(), endpoint.getEndpointURI().toString()).getMessage());
1034 }
1035
1036 MessageDispatcher dispatcher = null;
1037 try
1038 {
1039 if (logger.isDebugEnabled())
1040 {
1041 logger.debug("Borrowing a dispatcher for endpoint: " + endpoint.getEndpointURI());
1042 }
1043
1044 dispatcher = (MessageDispatcher) dispatchers.borrowObject(endpoint);
1045
1046 if (logger.isDebugEnabled())
1047 {
1048 logger.debug("Borrowed a dispatcher for endpoint: " + endpoint.getEndpointURI() + " = "
1049 + dispatcher.toString());
1050 }
1051
1052 return dispatcher;
1053 }
1054 catch (Exception ex)
1055 {
1056 throw new ConnectorException(CoreMessages.connectorCausedError(), this, ex);
1057 }
1058 finally
1059 {
1060 try
1061 {
1062 if (logger.isDebugEnabled())
1063 {
1064 logger.debug("Borrowed dispatcher: " + ObjectUtils.toString(dispatcher, "null"));
1065 }
1066 }
1067 catch (Exception ex)
1068 {
1069 throw new ConnectorException(CoreMessages.connectorCausedError(), this, ex);
1070 }
1071 }
1072 }
1073
1074 private void returnDispatcher(OutboundEndpoint endpoint, MessageDispatcher dispatcher)
1075 {
1076 if (endpoint != null && dispatcher != null)
1077 {
1078 if (logger.isDebugEnabled())
1079 {
1080 logger.debug("Returning dispatcher for endpoint: " + endpoint.getEndpointURI() + " = "
1081 + dispatcher.toString());
1082 }
1083
1084 try
1085 {
1086 dispatchers.returnObject(endpoint, dispatcher);
1087 }
1088 catch (Exception e)
1089 {
1090
1091
1092 logger.error("Failed to dispose dispatcher for endpoint: " + endpoint
1093 + ". This will cause a memory leak. Please report to", e);
1094 }
1095
1096 }
1097 }
1098
1099
1100
1101
1102
1103
1104
1105 public int getMaxRequestersActive()
1106 {
1107 return this.requesters.getMaxActive();
1108 }
1109
1110
1111
1112
1113
1114
1115
1116 public void setMaxRequestersActive(int maxActive)
1117 {
1118 this.requesters.setMaxActive(maxActive);
1119
1120 this.requesters.setMaxIdle(maxActive);
1121
1122
1123 this.requesters.setMaxTotal(20 * maxActive);
1124 }
1125
1126 private MessageRequester getRequester(InboundEndpoint endpoint) throws MuleException
1127 {
1128 if (!isStarted())
1129 {
1130 throw new LifecycleException(CoreMessages.lifecycleErrorCannotUseConnector(getName(),
1131 lifecycleManager.getCurrentPhase()), this);
1132 }
1133
1134 if (endpoint == null)
1135 {
1136 throw new IllegalArgumentException("Endpoint must not be null");
1137 }
1138
1139 if (!supportsProtocol(endpoint.getConnector().getProtocol()))
1140 {
1141 throw new IllegalArgumentException(CoreMessages.connectorSchemeIncompatibleWithEndpointScheme(
1142 this.getProtocol(), endpoint.getEndpointURI().toString()).getMessage());
1143 }
1144
1145 MessageRequester requester = null;
1146 try
1147 {
1148 if (logger.isDebugEnabled())
1149 {
1150 logger.debug("Borrowing a requester for endpoint: " + endpoint.getEndpointURI());
1151 }
1152
1153 requester = (MessageRequester) requesters.borrowObject(endpoint);
1154
1155 if (logger.isDebugEnabled())
1156 {
1157 logger.debug("Borrowed a requester for endpoint: " + endpoint.getEndpointURI() + " = "
1158 + requester.toString());
1159 }
1160
1161 return requester;
1162 }
1163 catch (Exception ex)
1164 {
1165 throw new ConnectorException(CoreMessages.connectorCausedError(), this, ex);
1166 }
1167 finally
1168 {
1169 try
1170 {
1171 if (logger.isDebugEnabled())
1172 {
1173 logger.debug("Borrowed requester: " + ObjectUtils.toString(requester, "null"));
1174 }
1175 }
1176 catch (Exception ex)
1177 {
1178 throw new ConnectorException(CoreMessages.connectorCausedError(), this, ex);
1179 }
1180 }
1181 }
1182
1183 private void returnRequester(InboundEndpoint endpoint, MessageRequester requester)
1184 {
1185 if (endpoint != null && requester != null)
1186 {
1187 if (logger.isDebugEnabled())
1188 {
1189 logger.debug("Returning requester for endpoint: " + endpoint.getEndpointURI() + " = "
1190 + requester.toString());
1191 }
1192
1193 try
1194 {
1195 requesters.returnObject(endpoint, requester);
1196 }
1197 catch (Exception e)
1198 {
1199
1200
1201 logger.error("Failed to dispose requester for endpoint: " + endpoint
1202 + ". This will cause a memory leak. Please report to", e);
1203 }
1204 }
1205
1206 }
1207
1208 @Override
1209 public void registerListener(InboundEndpoint endpoint,
1210 MessageProcessor messageProcessorChain,
1211 FlowConstruct flowConstruct) throws Exception
1212 {
1213 if (endpoint == null)
1214 {
1215 throw new IllegalArgumentException("The endpoint cannot be null when registering a listener");
1216 }
1217
1218 if (messageProcessorChain == null)
1219 {
1220 throw new IllegalArgumentException("The messageProcessorChain cannot be null when registering a listener");
1221 }
1222
1223 EndpointURI endpointUri = endpoint.getEndpointURI();
1224 if (endpointUri == null)
1225 {
1226 throw new ConnectorException(CoreMessages.endpointIsNullForListener(), this);
1227 }
1228
1229 logger.info("Registering listener: " + flowConstruct.getName() + " on endpointUri: "
1230 + endpointUri.toString());
1231
1232 if (getReceiver(flowConstruct, endpoint) != null)
1233 {
1234 throw new ConnectorException(CoreMessages.listenerAlreadyRegistered(endpointUri), this);
1235 }
1236
1237 MessageReceiver receiver = createReceiver(flowConstruct, endpoint);
1238 receiver.setListener(messageProcessorChain);
1239
1240 Object receiverKey = getReceiverKey(flowConstruct, endpoint);
1241 receiver.setReceiverKey(receiverKey.toString());
1242
1243 receiver.initialise();
1244 receivers.put(receiverKey, receiver);
1245
1246 if (isConnected())
1247 {
1248 receiver.connect();
1249 }
1250
1251 if (isStarted())
1252 {
1253 receiver.start();
1254 }
1255 }
1256
1257
1258
1259
1260
1261
1262
1263
1264 protected Object getReceiverKey(FlowConstruct flowConstruct, InboundEndpoint endpoint)
1265 {
1266 return StringUtils.defaultIfEmpty(endpoint.getEndpointURI().getFilterAddress(),
1267 endpoint.getEndpointURI().getAddress());
1268 }
1269
1270 @Override
1271 public final void unregisterListener(InboundEndpoint endpoint, FlowConstruct flowConstruct) throws Exception
1272 {
1273 if (endpoint == null)
1274 {
1275 throw new IllegalArgumentException("The endpoint must not be null when you unregister a listener");
1276 }
1277
1278 EndpointURI endpointUri = endpoint.getEndpointURI();
1279 if (endpointUri == null)
1280 {
1281 throw new IllegalArgumentException(
1282 "The endpointUri must not be null when you unregister a listener");
1283 }
1284
1285 if (logger.isInfoEnabled())
1286 {
1287 logger.info("Removing listener on endpointUri: " + endpointUri);
1288 }
1289
1290 if (receivers != null && !receivers.isEmpty())
1291 {
1292 MessageReceiver receiver = receivers.remove(getReceiverKey(flowConstruct, endpoint));
1293 if (receiver != null)
1294 {
1295
1296 destroyReceiver(receiver, endpoint);
1297 doUnregisterListener(flowConstruct, endpoint, receiver);
1298 }
1299 }
1300 }
1301
1302 protected void doUnregisterListener(FlowConstruct flowConstruct, InboundEndpoint endpoint, MessageReceiver receiver)
1303 {
1304
1305 }
1306
1307
1308
1309
1310
1311
1312 public ThreadingProfile getDispatcherThreadingProfile()
1313 {
1314 if (dispatcherThreadingProfile == null && muleContext != null)
1315 {
1316 dispatcherThreadingProfile = muleContext.getDefaultMessageDispatcherThreadingProfile();
1317 }
1318 return dispatcherThreadingProfile;
1319 }
1320
1321
1322
1323
1324
1325
1326
1327 public void setDispatcherThreadingProfile(ThreadingProfile dispatcherThreadingProfile)
1328 {
1329 this.dispatcherThreadingProfile = dispatcherThreadingProfile;
1330 }
1331
1332
1333
1334
1335
1336
1337 public ThreadingProfile getRequesterThreadingProfile()
1338 {
1339 if (requesterThreadingProfile == null && muleContext != null)
1340 {
1341 requesterThreadingProfile = muleContext.getDefaultMessageRequesterThreadingProfile();
1342 }
1343 return requesterThreadingProfile;
1344 }
1345
1346
1347
1348
1349
1350
1351
1352 public void setRequesterThreadingProfile(ThreadingProfile requesterThreadingProfile)
1353 {
1354 this.requesterThreadingProfile = requesterThreadingProfile;
1355 }
1356
1357
1358
1359
1360
1361
1362 public ThreadingProfile getReceiverThreadingProfile()
1363 {
1364 if (receiverThreadingProfile == null && muleContext != null)
1365 {
1366 receiverThreadingProfile = muleContext.getDefaultMessageReceiverThreadingProfile();
1367 }
1368 return receiverThreadingProfile;
1369 }
1370
1371
1372
1373
1374
1375
1376
1377 public void setReceiverThreadingProfile(ThreadingProfile receiverThreadingProfile)
1378 {
1379 this.receiverThreadingProfile = receiverThreadingProfile;
1380 }
1381
1382 public void destroyReceiver(MessageReceiver receiver, ImmutableEndpoint endpoint) throws Exception
1383 {
1384 receiver.dispose();
1385 }
1386
1387 protected abstract void doInitialise() throws InitialisationException;
1388
1389
1390
1391
1392 protected abstract void doDispose();
1393
1394
1395
1396
1397
1398
1399 protected abstract void doStart() throws MuleException;
1400
1401
1402
1403
1404
1405
1406 protected abstract void doStop() throws MuleException;
1407
1408 public List<Transformer> getDefaultInboundTransformers(ImmutableEndpoint endpoint)
1409 {
1410 if (serviceDescriptor == null)
1411 {
1412 throw new RuntimeException("serviceDescriptor not initialized");
1413 }
1414 return TransformerUtils.getDefaultInboundTransformers(serviceDescriptor, endpoint);
1415 }
1416
1417 public List<Transformer> getDefaultResponseTransformers(ImmutableEndpoint endpoint)
1418 {
1419 if (serviceDescriptor == null)
1420 {
1421 throw new RuntimeException("serviceDescriptor not initialized");
1422 }
1423 return TransformerUtils.getDefaultResponseTransformers(serviceDescriptor, endpoint);
1424 }
1425
1426 public List<Transformer> getDefaultOutboundTransformers(ImmutableEndpoint endpoint)
1427 {
1428 if (serviceDescriptor == null)
1429 {
1430 throw new RuntimeException("serviceDescriptor not initialized");
1431 }
1432 return TransformerUtils.getDefaultOutboundTransformers(serviceDescriptor, endpoint);
1433 }
1434
1435
1436
1437
1438
1439
1440 public ReplyToHandler getReplyToHandler(ImmutableEndpoint endpoint)
1441 {
1442 return new DefaultReplyToHandler(muleContext);
1443 }
1444
1445
1446
1447
1448
1449
1450 public void fireNotification(ServerNotification notification)
1451 {
1452 cachedNotificationHandler.fireNotification(notification);
1453 }
1454
1455 @Override
1456 public boolean isResponseEnabled()
1457 {
1458 return false;
1459 }
1460
1461 public MessageReceiver getReceiver(FlowConstruct flowConstruct, InboundEndpoint endpoint)
1462 {
1463 if (receivers != null)
1464 {
1465 Object key = getReceiverKey(flowConstruct, endpoint);
1466 if (key != null)
1467 {
1468 return receivers.get(key);
1469 }
1470 else
1471 {
1472 throw new RuntimeException("getReceiverKey() returned a null key");
1473 }
1474 }
1475 else
1476 {
1477 throw new RuntimeException("Connector has not been initialized.");
1478 }
1479 }
1480
1481
1482
1483
1484
1485
1486 public Map<Object, MessageReceiver> getReceivers()
1487 {
1488 return Collections.unmodifiableMap(receivers);
1489 }
1490
1491 public MessageReceiver lookupReceiver(String key)
1492 {
1493 if (key != null)
1494 {
1495 return receivers.get(key);
1496 }
1497 else
1498 {
1499 throw new IllegalArgumentException("Receiver key must not be null");
1500 }
1501 }
1502
1503 public MessageReceiver[] getReceivers(String wildcardExpression)
1504 {
1505 WildcardFilter filter = new WildcardFilter(wildcardExpression);
1506 filter.setCaseSensitive(false);
1507
1508 List<MessageReceiver> found = new ArrayList<MessageReceiver>();
1509
1510 for (Map.Entry<Object, MessageReceiver> e : receivers.entrySet())
1511 {
1512 if (filter.accept(e.getKey()))
1513 {
1514 found.add(e.getValue());
1515 }
1516 }
1517
1518 return CollectionUtils.toArrayOfComponentType(found, MessageReceiver.class);
1519 }
1520
1521 @Override
1522 public void connect() throws Exception
1523 {
1524 if (lifecycleManager.getState().isDisposed())
1525 {
1526 throw new LifecycleException(CoreMessages.lifecycleErrorCannotUseConnector(getName(),
1527 lifecycleManager.getCurrentPhase()), this);
1528 }
1529 if (isConnected())
1530 {
1531 return;
1532 }
1533
1534 RetryCallback callback = new RetryCallback()
1535 {
1536 @Override
1537 public void doWork(RetryContext context) throws Exception
1538 {
1539
1540 if (validateConnections && context.getLastFailure() instanceof ConnectException)
1541 {
1542 Connectable failed = ((ConnectException) context.getLastFailure()).getFailed();
1543 if (!failed.validateConnection(context).isOk())
1544 {
1545 throw new ConnectException(
1546 MessageFactory.createStaticMessage("Still unable to connect to resource " + failed.getClass().getName()),
1547 context.getLastFailure(), failed);
1548 }
1549 }
1550 doConnect();
1551
1552 if (receivers != null)
1553 {
1554 for (MessageReceiver receiver : receivers.values())
1555 {
1556 final List<MuleException> errors = new ArrayList<MuleException>();
1557 try
1558 {
1559 if (logger.isDebugEnabled())
1560 {
1561 logger.debug("Connecting receiver on endpoint: " + receiver.getEndpoint().getEndpointURI());
1562 }
1563 receiver.connect();
1564 if (isStarted())
1565 {
1566 receiver.start();
1567 }
1568 }
1569 catch (MuleException e)
1570 {
1571 logger.error(e);
1572 errors.add(e);
1573 }
1574
1575 if (!errors.isEmpty())
1576 {
1577
1578
1579
1580
1581
1582 throw errors.get(0);
1583 }
1584 }
1585 }
1586
1587 setConnected(true);
1588 setConnecting(false);
1589 logger.info("Connected: " + getWorkDescription());
1590
1591 if (startOnConnect && !isStarted() && !isStarting())
1592 {
1593 startAfterConnect();
1594 }
1595 }
1596
1597 @Override
1598 public String getWorkDescription()
1599 {
1600 return getConnectionDescription();
1601 }
1602 };
1603
1604 if (connecting.compareAndSet(false, true))
1605 {
1606 if (logger.isDebugEnabled())
1607 {
1608 logger.debug("Connecting: " + this);
1609 }
1610 retryPolicyTemplate.execute(callback, muleContext.getWorkManager());
1611 }
1612 }
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623 @Override
1624 public RetryContext validateConnection(RetryContext retryContext)
1625 {
1626 retryContext.setOk();
1627 return retryContext;
1628 }
1629
1630 @Override
1631 public void disconnect() throws Exception
1632 {
1633 if (isStarted())
1634 {
1635 startOnConnect = true;
1636 stop();
1637 }
1638
1639 if (receivers != null)
1640 {
1641 for (MessageReceiver receiver : receivers.values())
1642 {
1643 if (logger.isDebugEnabled())
1644 {
1645 logger.debug("Disconnecting receiver on endpoint: "
1646 + receiver.getEndpoint().getEndpointURI());
1647 }
1648 try
1649 {
1650 receiver.disconnect();
1651 }
1652 catch (Exception e)
1653 {
1654 logger.error(e.getMessage(), e);
1655 }
1656 }
1657 }
1658 try
1659 {
1660 if (isStarted() && !isStopping())
1661 {
1662 stop();
1663 }
1664 this.doDisconnect();
1665 if (logger.isInfoEnabled())
1666 {
1667 logger.info("Disconnected: " + this.getConnectionDescription());
1668 }
1669 this.fireNotification(new ConnectionNotification(this, getConnectEventId(),
1670 ConnectionNotification.CONNECTION_DISCONNECTED));
1671 }
1672 catch (Exception e)
1673 {
1674 logger.error(e.getMessage());
1675 }
1676 finally
1677 {
1678 connected.set(false);
1679 }
1680 }
1681
1682 @Override
1683 public String getConnectionDescription()
1684 {
1685 return this.toString();
1686 }
1687
1688 @Override
1689 public final boolean isConnected()
1690 {
1691 return connected.get();
1692 }
1693
1694 public final void setConnected(boolean flag)
1695 {
1696 connected.set(flag);
1697 }
1698
1699 public final void setConnecting(boolean flag)
1700 {
1701 connecting.set(flag);
1702 }
1703
1704 public final boolean isConnecting()
1705 {
1706 return connecting.get();
1707 }
1708
1709
1710
1711
1712
1713
1714 protected abstract void doConnect() throws Exception;
1715
1716
1717
1718
1719
1720
1721
1722 protected abstract void doDisconnect() throws Exception;
1723
1724
1725
1726
1727
1728
1729 protected String getConnectEventId()
1730 {
1731 return getName();
1732 }
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743 public boolean isCreateMultipleTransactedReceivers()
1744 {
1745 return createMultipleTransactedReceivers;
1746 }
1747
1748
1749
1750
1751
1752
1753
1754 public void setCreateMultipleTransactedReceivers(boolean createMultipleTransactedReceivers)
1755 {
1756 this.createMultipleTransactedReceivers = createMultipleTransactedReceivers;
1757 }
1758
1759
1760
1761
1762
1763
1764
1765 public int getNumberOfConcurrentTransactedReceivers()
1766 {
1767 return this.numberOfConcurrentTransactedReceivers;
1768 }
1769
1770
1771
1772
1773
1774 public void setNumberOfConcurrentTransactedReceivers(int count)
1775 {
1776 this.numberOfConcurrentTransactedReceivers = count;
1777 }
1778
1779 public void setDynamicNotification(boolean dynamic)
1780 {
1781 dynamicNotification = dynamic;
1782 }
1783
1784 protected void updateCachedNotificationHandler()
1785 {
1786 if (null != muleContext)
1787 {
1788 if (dynamicNotification)
1789 {
1790 cachedNotificationHandler = muleContext.getNotificationManager();
1791 }
1792 else
1793 {
1794 cachedNotificationHandler = new OptimisedNotificationHandler(
1795 muleContext.getNotificationManager(), EndpointMessageNotification.class);
1796 }
1797 }
1798 }
1799
1800 public boolean isEnableMessageEvents()
1801 {
1802 return cachedNotificationHandler.isNotificationEnabled(EndpointMessageNotification.class);
1803 }
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815 public void registerSupportedProtocol(String protocol)
1816 {
1817 protocol = protocol.toLowerCase();
1818 if (protocol.startsWith(getProtocol().toLowerCase()))
1819 {
1820 registerSupportedProtocolWithoutPrefix(protocol);
1821 }
1822 else
1823 {
1824 supportedProtocols.add(getProtocol().toLowerCase() + ":" + protocol);
1825 }
1826 }
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837 public void registerSupportedMetaProtocol(String protocol)
1838 {
1839 supportedProtocols.add(protocol.toLowerCase() + ":" + getProtocol().toLowerCase());
1840
1841 }
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855 protected void registerSupportedProtocolWithoutPrefix(String protocol)
1856 {
1857 supportedProtocols.add(protocol.toLowerCase());
1858 }
1859
1860 public void unregisterSupportedProtocol(String protocol)
1861 {
1862 protocol = protocol.toLowerCase();
1863 if (protocol.startsWith(getProtocol().toLowerCase()))
1864 {
1865 supportedProtocols.remove(protocol);
1866 }
1867 else
1868 {
1869 supportedProtocols.remove(getProtocol().toLowerCase() + ":" + protocol);
1870 }
1871 }
1872
1873
1874
1875
1876 @Override
1877 public boolean supportsProtocol(String protocol)
1878 {
1879 return supportedProtocols.contains(protocol.toLowerCase());
1880 }
1881
1882
1883
1884
1885
1886
1887 public List getSupportedProtocols()
1888 {
1889 return Collections.unmodifiableList(supportedProtocols);
1890 }
1891
1892
1893
1894
1895
1896
1897 public void setSupportedProtocols(List supportedProtocols)
1898 {
1899 for (Iterator iterator = supportedProtocols.iterator(); iterator.hasNext();)
1900 {
1901 String s = (String) iterator.next();
1902 registerSupportedProtocol(s);
1903 }
1904 }
1905
1906
1907
1908
1909 protected WorkManager getReceiverWorkManager() throws MuleException
1910 {
1911 return receiverWorkManager.get();
1912 }
1913
1914
1915
1916
1917
1918
1919 protected WorkManager getDispatcherWorkManager() throws MuleException
1920 {
1921 return dispatcherWorkManager.get();
1922 }
1923
1924
1925
1926
1927
1928
1929 protected WorkManager getRequesterWorkManager() throws MuleException
1930 {
1931 return requesterWorkManager.get();
1932 }
1933
1934
1935
1936
1937
1938
1939 public ScheduledExecutorService getScheduler()
1940 {
1941 return scheduler;
1942 }
1943
1944 protected ScheduledExecutorService createScheduler()
1945 {
1946
1947
1948 ThreadFactory threadFactory = new NamedThreadFactory(this.getName() + ".scheduler", muleContext.getExecutionClassLoader());
1949 ScheduledThreadPoolExecutor newExecutor = new ScheduledThreadPoolExecutor(4, threadFactory);
1950 newExecutor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
1951 newExecutor.setKeepAliveTime(this.getReceiverThreadingProfile().getThreadTTL(), TimeUnit.MILLISECONDS);
1952 newExecutor.allowCoreThreadTimeOut(true);
1953 return newExecutor;
1954 }
1955
1956
1957
1958
1959
1960
1961 @Override
1962 public SessionHandler getSessionHandler()
1963 {
1964 return sessionHandler;
1965 }
1966
1967
1968
1969
1970
1971
1972 public void setSessionHandler(SessionHandler sessionHandler)
1973 {
1974 this.sessionHandler = sessionHandler;
1975 }
1976
1977 @Override
1978 public void workAccepted(WorkEvent event)
1979 {
1980 handleWorkException(event, "workAccepted");
1981 }
1982
1983 @Override
1984 public void workRejected(WorkEvent event)
1985 {
1986 handleWorkException(event, "workRejected");
1987 }
1988
1989 @Override
1990 public void workStarted(WorkEvent event)
1991 {
1992 handleWorkException(event, "workStarted");
1993 }
1994
1995 @Override
1996 public void workCompleted(WorkEvent event)
1997 {
1998 handleWorkException(event, "workCompleted");
1999 }
2000
2001 protected void handleWorkException(WorkEvent event, String type)
2002 {
2003 if (event == null)
2004 {
2005 return;
2006 }
2007
2008 Throwable e = event.getException();
2009
2010 if (e == null)
2011 {
2012 return;
2013 }
2014
2015 if (e.getCause() != null)
2016 {
2017 e = e.getCause();
2018 }
2019
2020 logger.error("Work caused exception on '" + type + "'. Work being executed was: "
2021 + event.getWork().toString());
2022
2023 if (e instanceof MessagingException)
2024 {
2025 MuleEvent failedEvent = ((MessagingException) e).getEvent();
2026 failedEvent.getFlowConstruct().getExceptionListener().handleException((MessagingException) e, failedEvent);
2027 }
2028 else if (e instanceof Exception)
2029 {
2030 muleContext.getExceptionListener().handleException((Exception) e);
2031 }
2032 else
2033 {
2034 muleContext.getExceptionListener().handleException(
2035 new MuleRuntimeException(CoreMessages.connectorCausedError(this.getName()), e));
2036 }
2037 }
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048 protected void setupDispatchReturn(final OutboundEndpoint endpoint,
2049 final MessageDispatcher dispatcher,
2050 MuleMessage result)
2051 {
2052 if (result != null && result.getPayload() instanceof InputStream)
2053 {
2054 DelegatingInputStream is = new DelegatingInputStream((InputStream) result.getPayload())
2055 {
2056 @Override
2057 public void close() throws IOException
2058 {
2059 try
2060 {
2061 super.close();
2062 }
2063 finally
2064 {
2065 returnDispatcher(endpoint, dispatcher);
2066 }
2067 }
2068 };
2069 result.setPayload(is);
2070 }
2071 else
2072 {
2073
2074 this.returnDispatcher(endpoint, dispatcher);
2075 }
2076 }
2077
2078 @Override
2079 public MuleMessage request(String uri, long timeout) throws Exception
2080 {
2081 return request(getMuleContext().getEndpointFactory().getInboundEndpoint(uri),
2082 timeout);
2083 }
2084
2085 @Override
2086 public MuleMessage request(InboundEndpoint endpoint, long timeout) throws Exception
2087 {
2088 MessageRequester requester = null;
2089 MuleMessage result = null;
2090
2091 try
2092 {
2093 requester = this.getRequester(endpoint);
2094 result = requester.request(timeout);
2095 return result;
2096 }
2097 finally
2098 {
2099 setupRequestReturn(endpoint, requester, result);
2100 }
2101 }
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112 protected void setupRequestReturn(final InboundEndpoint endpoint,
2113 final MessageRequester requester,
2114 MuleMessage result)
2115 {
2116 if (result != null && result.getPayload() instanceof InputStream)
2117 {
2118 DelegatingInputStream is = new DelegatingInputStream((InputStream) result.getPayload())
2119 {
2120 @Override
2121 public void close() throws IOException
2122 {
2123 try
2124 {
2125 super.close();
2126 }
2127 finally
2128 {
2129 returnRequester(endpoint, requester);
2130 }
2131 }
2132 };
2133 result.setPayload(is);
2134 }
2135 else
2136 {
2137
2138 this.returnRequester(endpoint, requester);
2139 }
2140 }
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156 public void initialiseFromUrl(EndpointURI endpointUri) throws InitialisationException
2157 {
2158 if (!supportsProtocol(endpointUri.getFullScheme()))
2159 {
2160 throw new InitialisationException(CoreMessages.schemeNotCompatibleWithConnector(
2161 endpointUri.getFullScheme(), this.getClass()), this);
2162 }
2163 Properties props = new Properties();
2164 props.putAll(endpointUri.getParams());
2165
2166 if (endpointUri.getUserInfo() != null)
2167 {
2168 props.setProperty("username", endpointUri.getUser());
2169 String passwd = endpointUri.getPassword();
2170 if (passwd != null)
2171 {
2172 props.setProperty("password", passwd);
2173 }
2174 }
2175 String host = endpointUri.getHost();
2176 if (host != null)
2177 {
2178 props.setProperty("hostname", host);
2179 props.setProperty("host", host);
2180 }
2181 if (endpointUri.getPort() > -1)
2182 {
2183 props.setProperty("port", String.valueOf(endpointUri.getPort()));
2184 }
2185
2186 org.mule.util.BeanUtils.populateWithoutFail(this, props, true);
2187
2188 setName(new ObjectNameHelper(muleContext).getConnectorName(this));
2189
2190 }
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200 protected synchronized void initFromServiceDescriptor() throws InitialisationException
2201 {
2202 try
2203 {
2204 serviceDescriptor = (TransportServiceDescriptor) muleContext.getRegistry()
2205 .lookupServiceDescriptor(ServiceType.TRANSPORT, getProtocol().toLowerCase(), serviceOverrides);
2206 if (serviceDescriptor == null)
2207 {
2208 throw new ServiceException(CoreMessages.noServiceTransportDescriptor(getProtocol()));
2209 }
2210
2211 if (logger.isDebugEnabled())
2212 {
2213 logger.debug("Loading DispatcherFactory for connector: " + getName() + " ("
2214 + getClass().getName() + ")");
2215 }
2216
2217 MessageDispatcherFactory df = serviceDescriptor.createDispatcherFactory();
2218 if (df != null)
2219 {
2220 this.setDispatcherFactory(df);
2221 }
2222 else if (logger.isDebugEnabled())
2223 {
2224 logger.debug("Transport '" + getProtocol() + "' will not support outbound endpoints: ");
2225 }
2226
2227 if (logger.isDebugEnabled())
2228 {
2229 logger.debug("Loading RequesterFactory for connector: " + getName() + " ("
2230 + getClass().getName() + ")");
2231 }
2232
2233 MessageRequesterFactory rf = serviceDescriptor.createRequesterFactory();
2234 if (rf != null)
2235 {
2236 this.setRequesterFactory(rf);
2237 }
2238 else if (logger.isDebugEnabled())
2239 {
2240 logger.debug("Transport '" + getProtocol() + "' will not support requests: ");
2241 }
2242
2243 sessionHandler = serviceDescriptor.createSessionHandler();
2244 }
2245 catch (Exception e)
2246 {
2247 throw new InitialisationException(e, this);
2248 }
2249 }
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259 protected TransportServiceDescriptor getServiceDescriptor()
2260 {
2261 if (serviceDescriptor == null)
2262 {
2263 throw new IllegalStateException("This connector has not yet been initialised: " + name);
2264 }
2265 return serviceDescriptor;
2266 }
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281 protected MessageReceiver createReceiver(FlowConstruct flowConstruct, InboundEndpoint endpoint) throws Exception
2282 {
2283 return getServiceDescriptor().createMessageReceiver(this, flowConstruct, endpoint);
2284 }
2285
2286
2287
2288
2289
2290
2291
2292 public Map getServiceOverrides()
2293 {
2294 return serviceOverrides;
2295 }
2296
2297
2298
2299
2300
2301
2302 public void setServiceOverrides(Map serviceOverrides)
2303 {
2304 this.serviceOverrides = new Properties();
2305 this.serviceOverrides.putAll(serviceOverrides);
2306 }
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320 @Override
2321 public OutputStream getOutputStream(OutboundEndpoint endpoint, MuleEvent event) throws MuleException
2322 {
2323 throw new UnsupportedOperationException(CoreMessages.streamingNotSupported(this.getProtocol()).toString());
2324 }
2325
2326 @Override
2327 public MuleContext getMuleContext()
2328 {
2329 return muleContext;
2330 }
2331
2332 @Override
2333 public String toString()
2334 {
2335 final StringBuffer sb = new StringBuffer(120);
2336 final String nl = System.getProperty("line.separator");
2337 sb.append(ClassUtils.getSimpleName(this.getClass()));
2338
2339 sb.append(nl);
2340 sb.append("{");
2341 sb.append(nl);
2342 sb.append(" name=").append(name);
2343 sb.append(nl);
2344 sb.append(" lifecycle=").append(
2345 lifecycleManager == null ? "<not in lifecycle>" : lifecycleManager.getCurrentPhase());
2346 sb.append(nl);
2347 sb.append(" this=").append(Integer.toHexString(System.identityHashCode(this)));
2348 sb.append(nl);
2349 sb.append(" numberOfConcurrentTransactedReceivers=").append(numberOfConcurrentTransactedReceivers);
2350 sb.append(nl);
2351 sb.append(" createMultipleTransactedReceivers=").append(createMultipleTransactedReceivers);
2352 sb.append(nl);
2353 sb.append(" connected=").append(connected);
2354 sb.append(nl);
2355 sb.append(" supportedProtocols=").append(supportedProtocols);
2356 sb.append(nl);
2357 sb.append(" serviceOverrides=");
2358 if (serviceOverrides != null)
2359 {
2360 for (Map.Entry<Object, Object> entry : serviceOverrides.entrySet())
2361 {
2362 sb.append(nl);
2363 sb.append(" ").append(String.format("%s=%s", entry.getKey(), entry.getValue()));
2364 }
2365 }
2366 else
2367 {
2368 sb.append("<none>");
2369 }
2370 sb.append(nl);
2371 sb.append('}');
2372 sb.append(nl);
2373 return sb.toString();
2374 }
2375
2376 @Override
2377 public RetryPolicyTemplate getRetryPolicyTemplate()
2378 {
2379 return retryPolicyTemplate;
2380 }
2381
2382 public void setRetryPolicyTemplate(RetryPolicyTemplate retryPolicyTemplate)
2383 {
2384 this.retryPolicyTemplate = retryPolicyTemplate;
2385 }
2386
2387
2388
2389
2390 public boolean isValidateConnections()
2391 {
2392 return validateConnections;
2393 }
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409 public void setValidateConnections(final boolean validateConnections)
2410 {
2411 this.validateConnections = validateConnections;
2412 }
2413
2414
2415
2416
2417
2418
2419
2420 public void setDispatcherPoolWhenExhaustedAction(byte whenExhaustedAction)
2421 {
2422 checkDispatchersInitialised();
2423 dispatchers.setWhenExhaustedAction(whenExhaustedAction);
2424 }
2425
2426
2427
2428
2429
2430 public void setDispatcherPoolMaxWait(int maxWait)
2431 {
2432 checkDispatchersInitialised();
2433 dispatchers.setMaxWait(maxWait);
2434 }
2435
2436
2437
2438
2439 public void setDispatcherPoolFactory(ConfigurableKeyedObjectPoolFactory dispatcherPoolFactory)
2440 {
2441 this.dispatcherPoolFactory = dispatcherPoolFactory;
2442 }
2443
2444 public ConfigurableKeyedObjectPoolFactory getDispatcherPoolFactory()
2445 {
2446 return dispatcherPoolFactory;
2447 }
2448
2449
2450
2451
2452
2453 public void setRequesterPoolWhenExhaustedAction(byte whenExhaustedAction)
2454 {
2455 requesters.setWhenExhaustedAction(whenExhaustedAction);
2456 }
2457
2458
2459
2460
2461
2462 public void setRequesterPoolMaxWait(int maxWait)
2463 {
2464 requesters.setMaxWait(maxWait);
2465 }
2466
2467 public MessageProcessor createDispatcherMessageProcessor(OutboundEndpoint endpoint) throws MuleException
2468 {
2469 if (endpoint.getExchangePattern().hasResponse() || !getDispatcherThreadingProfile().isDoThreading())
2470 {
2471 return new DispatcherMessageProcessor(endpoint);
2472 }
2473 else
2474 {
2475 DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder();
2476 builder.setName("dispatcher processor chain for '" + endpoint.getAddress() + "'");
2477 LaxAsyncInterceptingMessageProcessor async = new LaxAsyncInterceptingMessageProcessor(
2478 new WorkManagerSource()
2479 {
2480 @Override
2481 public WorkManager getWorkManager() throws MuleException
2482 {
2483 return getDispatcherWorkManager();
2484 }
2485 });
2486 builder.chain(async);
2487 builder.chain(new DispatcherMessageProcessor(endpoint));
2488 return builder.build();
2489 }
2490 }
2491
2492 @Override
2493 public MessageExchangePattern getDefaultExchangePattern()
2494 {
2495 try
2496 {
2497 return serviceDescriptor.getDefaultExchangePattern();
2498 }
2499 catch (TransportServiceException tse)
2500 {
2501 throw new MuleRuntimeException(tse);
2502 }
2503 }
2504
2505 @Override
2506 public List<MessageExchangePattern> getInboundExchangePatterns()
2507 {
2508 try
2509 {
2510 return serviceDescriptor.getInboundExchangePatterns();
2511 }
2512 catch (TransportServiceException tse)
2513 {
2514 throw new MuleRuntimeException(tse);
2515 }
2516 }
2517
2518 @Override
2519 public List<MessageExchangePattern> getOutboundExchangePatterns()
2520 {
2521 try
2522 {
2523 return serviceDescriptor.getOutboundExchangePatterns();
2524 }
2525 catch (TransportServiceException tse)
2526 {
2527 throw new MuleRuntimeException(tse);
2528 }
2529 }
2530
2531 class DispatcherMessageProcessor implements MessageProcessor
2532 {
2533 private OutboundNotificationMessageProcessor notificationMessageProcessor;
2534 private OutboundEndpoint endpoint;
2535
2536 public DispatcherMessageProcessor(OutboundEndpoint endpoint)
2537 {
2538 this.endpoint = endpoint;
2539 }
2540
2541 @Override
2542 public MuleEvent process(MuleEvent event) throws MuleException
2543 {
2544 MessageDispatcher dispatcher = null;
2545 try
2546 {
2547 dispatcher = getDispatcher(endpoint);
2548 if (notificationMessageProcessor == null)
2549 {
2550 notificationMessageProcessor = new OutboundNotificationMessageProcessor(endpoint);
2551 }
2552 EndpointMessageNotification beginNotification = notificationMessageProcessor.createBeginNotification(event);
2553 MuleEvent result = dispatcher.process(event);
2554
2555
2556 notificationMessageProcessor.dispatchNotification(beginNotification);
2557 notificationMessageProcessor.process(result != null ? result : event);
2558 return result;
2559
2560 }
2561 catch (DispatchException dex)
2562 {
2563 throw dex;
2564 }
2565 catch (MuleException ex)
2566 {
2567 throw new DispatchException(event, endpoint, ex);
2568 }
2569 finally
2570 {
2571 returnDispatcher(endpoint, dispatcher);
2572 }
2573 }
2574
2575 @Override
2576 public String toString()
2577 {
2578 return ObjectUtils.toString(this);
2579 }
2580 }
2581 }