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