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