1
2
3
4
5
6
7
8
9
10
11 package org.mule.providers;
12
13 import org.mule.MuleManager;
14 import org.mule.MuleRuntimeException;
15 import org.mule.config.ThreadingProfile;
16 import org.mule.config.i18n.CoreMessages;
17 import org.mule.impl.AlreadyInitialisedException;
18 import org.mule.impl.DefaultExceptionStrategy;
19 import org.mule.impl.ImmutableMuleEndpoint;
20 import org.mule.impl.MuleSessionHandler;
21 import org.mule.impl.internal.notifications.ConnectionNotification;
22 import org.mule.providers.service.TransportFactory;
23 import org.mule.providers.service.TransportServiceDescriptor;
24 import org.mule.providers.service.TransportServiceException;
25 import org.mule.routing.filters.WildcardFilter;
26 import org.mule.umo.MessagingException;
27 import org.mule.umo.UMOComponent;
28 import org.mule.umo.UMOEvent;
29 import org.mule.umo.UMOException;
30 import org.mule.umo.UMOMessage;
31 import org.mule.umo.endpoint.UMOEndpoint;
32 import org.mule.umo.endpoint.UMOEndpointURI;
33 import org.mule.umo.endpoint.UMOImmutableEndpoint;
34 import org.mule.umo.lifecycle.DisposeException;
35 import org.mule.umo.lifecycle.Initialisable;
36 import org.mule.umo.lifecycle.InitialisationException;
37 import org.mule.umo.manager.UMOServerNotification;
38 import org.mule.umo.manager.UMOWorkManager;
39 import org.mule.umo.provider.ConnectorException;
40 import org.mule.umo.provider.DispatchException;
41 import org.mule.umo.provider.UMOConnectable;
42 import org.mule.umo.provider.UMOConnector;
43 import org.mule.umo.provider.UMOMessageAdapter;
44 import org.mule.umo.provider.UMOMessageDispatcher;
45 import org.mule.umo.provider.UMOMessageDispatcherFactory;
46 import org.mule.umo.provider.UMOMessageReceiver;
47 import org.mule.umo.provider.UMOSessionHandler;
48 import org.mule.umo.provider.UMOStreamMessageAdapter;
49 import org.mule.umo.transformer.UMOTransformer;
50 import org.mule.util.ClassUtils;
51 import org.mule.util.CollectionUtils;
52 import org.mule.util.ObjectNameHelper;
53 import org.mule.util.ObjectUtils;
54 import org.mule.util.PropertiesUtils;
55 import org.mule.util.StringUtils;
56 import org.mule.util.concurrent.NamedThreadFactory;
57 import org.mule.util.concurrent.WaitableBoolean;
58
59 import java.beans.ExceptionListener;
60 import java.io.InputStream;
61 import java.io.OutputStream;
62 import java.util.ArrayList;
63 import java.util.Collections;
64 import java.util.HashMap;
65 import java.util.Iterator;
66 import java.util.List;
67 import java.util.Map;
68 import java.util.Properties;
69
70 import javax.resource.spi.work.WorkEvent;
71 import javax.resource.spi.work.WorkListener;
72
73 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
74 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentMap;
75 import edu.emory.mathcs.backport.java.util.concurrent.ScheduledExecutorService;
76 import edu.emory.mathcs.backport.java.util.concurrent.ScheduledThreadPoolExecutor;
77 import edu.emory.mathcs.backport.java.util.concurrent.ThreadFactory;
78 import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
79 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;
80 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicReference;
81 import org.apache.commons.beanutils.BeanUtils;
82 import org.apache.commons.logging.Log;
83 import org.apache.commons.logging.LogFactory;
84 import org.apache.commons.pool.KeyedPoolableObjectFactory;
85 import org.apache.commons.pool.impl.GenericKeyedObjectPool;
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112 public abstract class AbstractConnector
113 implements UMOConnector, ExceptionListener, UMOConnectable, WorkListener
114 {
115
116
117
118 public static final int DEFAULT_NUM_CONCURRENT_TX_RECEIVERS = 4;
119
120
121
122
123 protected final Log logger = LogFactory.getLog(getClass());
124
125
126
127
128 protected final AtomicBoolean started = new AtomicBoolean(false);
129
130
131
132
133 protected final AtomicBoolean initialised = new AtomicBoolean(false);
134
135
136
137
138 protected volatile String name;
139
140
141
142
143 protected volatile ExceptionListener exceptionListener;
144
145
146
147
148 protected final AtomicBoolean disposed = new AtomicBoolean(false);
149
150
151
152
153 protected final AtomicBoolean disposing = new AtomicBoolean(false);
154
155
156
157
158 protected volatile UMOMessageDispatcherFactory dispatcherFactory;
159
160
161
162
163 protected final GenericKeyedObjectPool dispatchers = new GenericKeyedObjectPool();
164
165
166
167
168 protected final ConcurrentMap receivers = new ConcurrentHashMap();
169
170
171
172
173 private volatile ThreadingProfile dispatcherThreadingProfile = MuleManager.getConfiguration()
174 .getMessageDispatcherThreadingProfile();
175
176
177
178
179 private volatile ThreadingProfile receiverThreadingProfile = MuleManager.getConfiguration()
180 .getMessageReceiverThreadingProfile();
181
182
183
184
185 protected volatile boolean createMultipleTransactedReceivers = true;
186
187
188
189
190 protected volatile int numberOfConcurrentTransactedReceivers = DEFAULT_NUM_CONCURRENT_TX_RECEIVERS;
191
192
193
194
195
196 protected volatile UMOTransformer defaultInboundTransformer;
197
198
199
200
201
202 protected volatile UMOTransformer defaultOutboundTransformer;
203
204
205
206
207
208 protected volatile UMOTransformer defaultResponseTransformer;
209
210 protected volatile ConnectionStrategy connectionStrategy;
211
212 protected final WaitableBoolean connected = new WaitableBoolean(false);
213
214 protected final WaitableBoolean connecting = new WaitableBoolean(false);
215
216
217
218
219
220 protected final WaitableBoolean startOnConnect = new WaitableBoolean(false);
221
222
223
224
225
226 private volatile boolean enableMessageEvents;
227
228 private final List supportedProtocols;
229
230
231
232
233 private final AtomicReference
234
235
236
237
238 private final AtomicReference
239
240
241
242
243 private final AtomicReference
244
245
246
247
248 protected volatile TransportServiceDescriptor serviceDescriptor;
249
250
251
252
253
254 protected volatile Properties serviceOverrides;
255
256
257
258
259
260 protected volatile UMOSessionHandler sessionHandler = new MuleSessionHandler();
261
262
263 public AbstractConnector()
264 {
265 super();
266
267
268 exceptionListener = new DefaultExceptionStrategy();
269 connectionStrategy = MuleManager.getConfiguration().getConnectionStrategy();
270 enableMessageEvents = MuleManager.getConfiguration().isEnableMessageEvents();
271
272
273 supportedProtocols = new ArrayList();
274 supportedProtocols.add(getProtocol().toLowerCase());
275
276
277
278
279 dispatchers.setTestOnBorrow(false);
280 dispatchers.setTestOnReturn(true);
281 }
282
283
284 public String getName()
285 {
286 return name;
287 }
288
289
290 public void setName(String newName)
291 {
292 if (newName == null)
293 {
294 throw new IllegalArgumentException(CoreMessages.objectIsNull("Connector name").toString());
295 }
296
297 if (logger.isDebugEnabled())
298 {
299 logger.debug("Set UMOConnector name to: " + newName);
300 }
301
302 name = newName;
303 }
304
305
306 public final synchronized void initialise() throws InitialisationException
307 {
308 if (initialised.get())
309 {
310 throw new AlreadyInitialisedException("Connector '" + getName() + "'", this);
311 }
312
313 if (logger.isInfoEnabled())
314 {
315 logger.info("Initialising: " + this);
316 }
317
318
319 this.initFromServiceDescriptor();
320
321
322
323
324 this.disposeDispatchers();
325 this.disposeReceivers();
326
327 this.doInitialise();
328
329 if (exceptionListener instanceof Initialisable)
330 {
331 ((Initialisable) exceptionListener).initialise();
332 }
333
334 initialised.set(true);
335 }
336
337
338 public final synchronized void startConnector() throws UMOException
339 {
340 this.checkDisposed();
341
342 if (!this.isStarted())
343 {
344 if (!this.isConnected())
345 {
346 startOnConnect.set(true);
347
348
349 connectionStrategy.connect(this);
350
351 return;
352 }
353
354 if (logger.isInfoEnabled())
355 {
356 logger.info("Starting: " + this);
357 }
358
359
360 ScheduledExecutorService currentScheduler = (ScheduledExecutorService) scheduler.get();
361 if (currentScheduler == null || currentScheduler.isShutdown())
362 {
363 scheduler.set(this.getScheduler());
364 }
365
366 this.doStart();
367 started.set(true);
368
369 if (receivers != null)
370 {
371 for (Iterator iterator = receivers.values().iterator(); iterator.hasNext();)
372 {
373 UMOMessageReceiver mr = (UMOMessageReceiver) iterator.next();
374 if (logger.isDebugEnabled())
375 {
376 logger.debug("Starting receiver on endpoint: " + mr.getEndpoint().getEndpointURI());
377 }
378 mr.start();
379 }
380 }
381
382 if (logger.isInfoEnabled())
383 {
384 logger.info("Started: " + this);
385 }
386 }
387 }
388
389
390 public boolean isStarted()
391 {
392 return started.get();
393 }
394
395
396 public final synchronized void stopConnector() throws UMOException
397 {
398 if (this.isDisposed())
399 {
400 return;
401 }
402
403 if (this.isStarted())
404 {
405 if (logger.isInfoEnabled())
406 {
407 logger.info("Stopping: " + this);
408 }
409
410
411 ((ScheduledExecutorService) scheduler.get()).shutdown();
412
413 this.doStop();
414 started.set(false);
415
416
417
418 if (receivers != null)
419 {
420 for (Iterator iterator = receivers.values().iterator(); iterator.hasNext();)
421 {
422 UMOMessageReceiver mr = (UMOMessageReceiver) iterator.next();
423 if (logger.isDebugEnabled())
424 {
425 logger.debug("Stopping receiver on endpoint: " + mr.getEndpoint().getEndpointURI());
426 }
427 mr.stop();
428 }
429 }
430 }
431
432 if (this.isConnected())
433 {
434 try
435 {
436 this.disconnect();
437 }
438 catch (Exception e)
439 {
440
441 logger.error("Failed to disconnect: " + e.getMessage(), e);
442 }
443 }
444
445
446 scheduler.set(null);
447
448
449
450
451 this.initialised.set(false);
452
453 if (logger.isInfoEnabled())
454 {
455 logger.info("Stopped: " + this);
456 }
457 }
458
459
460 public final synchronized void dispose()
461 {
462 disposing.set(true);
463
464 if (logger.isInfoEnabled())
465 {
466 logger.info("Disposing: " + this);
467 }
468
469 try
470 {
471 this.stopConnector();
472 }
473 catch (UMOException e)
474 {
475
476 logger.warn("Failed to stop during shutdown: " + e.getMessage(), e);
477 }
478
479 this.disposeReceivers();
480 this.disposeDispatchers();
481 this.disposeWorkManagers();
482
483 this.doDispose();
484 disposed.set(true);
485
486 if (logger.isInfoEnabled())
487 {
488 logger.info("Disposed: " + this);
489 }
490 }
491
492 protected void disposeWorkManagers()
493 {
494 logger.debug("Disposing dispatcher work manager");
495 UMOWorkManager workManager = (UMOWorkManager)dispatcherWorkManager.get();
496 if (workManager != null)
497 {
498 workManager.dispose();
499 }
500 dispatcherWorkManager.set(null);
501
502 logger.debug("Disposing receiver work manager");
503 workManager = (UMOWorkManager)receiverWorkManager.get();
504 if (workManager != null)
505 {
506 workManager.dispose();
507 }
508 receiverWorkManager.set(null);
509 }
510
511 protected void disposeReceivers()
512 {
513 if (receivers != null)
514 {
515 logger.debug("Disposing Receivers");
516
517 for (Iterator iterator = receivers.values().iterator(); iterator.hasNext();)
518 {
519 UMOMessageReceiver receiver = (UMOMessageReceiver) iterator.next();
520
521 try
522 {
523 this.destroyReceiver(receiver, receiver.getEndpoint());
524 }
525 catch (Throwable e)
526 {
527
528 logger.error("Failed to destroy receiver: " + receiver, e);
529 }
530 }
531
532 receivers.clear();
533 logger.debug("Receivers Disposed");
534 }
535 }
536
537 protected void disposeDispatchers()
538 {
539 if (dispatchers != null)
540 {
541 logger.debug("Disposing Dispatchers");
542
543 try
544 {
545
546
547
548 if (this.isDisposing())
549 {
550
551 dispatchers.close();
552 }
553 else
554 {
555 dispatchers.clear();
556 }
557 }
558 catch (Exception ex)
559 {
560
561
562 }
563
564 logger.debug("Dispatchers Disposed");
565 }
566 }
567
568
569 public boolean isDisposed()
570 {
571 return disposed.get();
572 }
573
574
575 public void handleException(Exception exception)
576 {
577 if (exceptionListener == null)
578 {
579 throw new MuleRuntimeException(
580 CoreMessages.exceptionOnConnectorNotExceptionListener(this.getName()), exception);
581 }
582 else
583 {
584 exceptionListener.exceptionThrown(exception);
585 }
586 }
587
588
589 public void exceptionThrown(Exception e)
590 {
591 handleException(e);
592 }
593
594
595
596
597
598 public ExceptionListener getExceptionListener()
599 {
600 return exceptionListener;
601 }
602
603
604
605
606
607 public void setExceptionListener(ExceptionListener listener)
608 {
609 exceptionListener = listener;
610 }
611
612
613
614
615 public UMOMessageDispatcherFactory getDispatcherFactory()
616 {
617 return dispatcherFactory;
618 }
619
620
621
622
623 public void setDispatcherFactory(UMOMessageDispatcherFactory dispatcherFactory)
624 {
625 KeyedPoolableObjectFactory poolFactory;
626
627 if (dispatcherFactory instanceof KeyedPoolableObjectFactory)
628 {
629 poolFactory = (KeyedPoolableObjectFactory) dispatcherFactory;
630 }
631 else
632 {
633
634 poolFactory = new KeyedPoolMessageDispatcherFactoryAdapter(dispatcherFactory);
635 }
636
637 this.dispatchers.setFactory(poolFactory);
638
639
640
641 this.dispatcherFactory = dispatcherFactory;
642 }
643
644
645
646
647
648
649
650 public int getMaxDispatchersActive()
651 {
652 return this.dispatchers.getMaxActive();
653 }
654
655
656
657
658
659
660
661 public void setMaxDispatchersActive(int maxActive)
662 {
663 this.dispatchers.setMaxActive(maxActive);
664
665 this.dispatchers.setMaxIdle(maxActive);
666 }
667
668 private UMOMessageDispatcher getDispatcher(UMOImmutableEndpoint endpoint) throws UMOException
669 {
670 this.checkDisposed();
671
672 if (endpoint == null)
673 {
674 throw new IllegalArgumentException("Endpoint must not be null");
675 }
676
677 if (!this.supportsProtocol(endpoint.getConnector().getProtocol()))
678 {
679 throw new IllegalArgumentException(
680 CoreMessages.connectorSchemeIncompatibleWithEndpointScheme(this.getProtocol(),
681 endpoint.getEndpointURI().toString()).getMessage());
682 }
683
684 try
685 {
686 if (logger.isDebugEnabled())
687 {
688 logger.debug("Borrowing a dispatcher for endpoint: " + endpoint.getEndpointURI());
689 }
690 }
691 catch (Exception ex)
692 {
693 throw new ConnectorException(CoreMessages.connectorCausedError(), this, ex);
694 }
695
696 UMOMessageDispatcher dispatcher = null;
697
698 try
699 {
700 dispatcher = (UMOMessageDispatcher) dispatchers.borrowObject(endpoint);
701 return dispatcher;
702 }
703 catch (Exception ex)
704 {
705 throw new ConnectorException(CoreMessages.connectorCausedError(), this, ex);
706 }
707 finally
708 {
709 try
710 {
711 if (logger.isDebugEnabled())
712 {
713 logger.debug("Borrowed dispatcher: " + ObjectUtils.toString(dispatcher, "null"));
714 }
715 }
716 catch (Exception ex)
717 {
718 throw new ConnectorException(CoreMessages.connectorCausedError(), this, ex);
719 }
720 }
721 }
722
723 private void returnDispatcher(UMOImmutableEndpoint endpoint, UMOMessageDispatcher dispatcher)
724 {
725 if (endpoint != null && dispatcher != null)
726 {
727 try
728 {
729 if (logger.isDebugEnabled())
730 {
731 logger.debug("Returning dispatcher for endpoint: " + endpoint.getEndpointURI() + " = "
732 + ObjectUtils.toString(dispatcher, "null"));
733 }
734 }
735 catch (Exception ex)
736 {
737
738
739
740 }
741 finally
742 {
743 try
744 {
745 dispatchers.returnObject(endpoint, dispatcher);
746 }
747 catch (Exception ex)
748 {
749
750
751 }
752 }
753 }
754 }
755
756 protected void checkDisposed() throws DisposeException
757 {
758 if (this.isDisposed())
759 {
760 throw new DisposeException(CoreMessages.cannotUseDisposedConnector(), this);
761 }
762 }
763
764
765 public UMOMessageReceiver registerListener(UMOComponent component, UMOEndpoint endpoint) throws Exception
766 {
767 if (endpoint == null)
768 {
769 throw new IllegalArgumentException("The endpoint cannot be null when registering a listener");
770 }
771
772 if (component == null)
773 {
774 throw new IllegalArgumentException("The component cannot be null when registering a listener");
775 }
776
777 UMOEndpointURI endpointUri = endpoint.getEndpointURI();
778 if (endpointUri == null)
779 {
780 throw new ConnectorException(CoreMessages.endpointIsNullForListener(), this);
781 }
782
783 logger.info("Registering listener: " + component.getDescriptor().getName() + " on endpointUri: "
784 + endpointUri.toString());
785
786 UMOMessageReceiver receiver = this.getReceiver(component, endpoint);
787
788 if (receiver != null)
789 {
790 throw new ConnectorException(CoreMessages.listenerAlreadyRegistered(endpointUri), this);
791 }
792 else
793 {
794 receiver = this.createReceiver(component, endpoint);
795 Object receiverKey = getReceiverKey(component, endpoint);
796 receiver.setReceiverKey(receiverKey.toString());
797 receivers.put(receiverKey, receiver);
798
799 }
800
801 return receiver;
802 }
803
804
805
806
807
808
809
810
811 protected Object getReceiverKey(UMOComponent component, UMOEndpoint endpoint)
812 {
813 return StringUtils.defaultIfEmpty(endpoint.getEndpointURI().getFilterAddress(), endpoint
814 .getEndpointURI().getAddress());
815 }
816
817
818 public final void unregisterListener(UMOComponent component, UMOEndpoint endpoint) throws Exception
819 {
820 if (component == null)
821 {
822 throw new IllegalArgumentException(
823 "The component must not be null when you unregister a listener");
824 }
825
826 if (endpoint == null)
827 {
828 throw new IllegalArgumentException("The endpoint must not be null when you unregister a listener");
829 }
830
831 UMOEndpointURI endpointUri = endpoint.getEndpointURI();
832 if (endpointUri == null)
833 {
834 throw new IllegalArgumentException(
835 "The endpointUri must not be null when you unregister a listener");
836 }
837
838 if (logger.isInfoEnabled())
839 {
840 logger.info("Removing listener on endpointUri: " + endpointUri);
841 }
842
843 if (receivers != null && !receivers.isEmpty())
844 {
845 UMOMessageReceiver receiver = (UMOMessageReceiver) receivers.remove(this.getReceiverKey(component,
846 endpoint));
847 if (receiver != null)
848 {
849 this.destroyReceiver(receiver, endpoint);
850 }
851 }
852 }
853
854
855
856
857
858
859 public ThreadingProfile getDispatcherThreadingProfile()
860 {
861 return dispatcherThreadingProfile;
862 }
863
864
865
866
867
868
869
870 public void setDispatcherThreadingProfile(ThreadingProfile dispatcherThreadingProfile)
871 {
872 this.dispatcherThreadingProfile = dispatcherThreadingProfile;
873 }
874
875
876
877
878
879
880 public ThreadingProfile getReceiverThreadingProfile()
881 {
882 return receiverThreadingProfile;
883 }
884
885
886
887
888
889
890
891 public void setReceiverThreadingProfile(ThreadingProfile receiverThreadingProfile)
892 {
893 this.receiverThreadingProfile = receiverThreadingProfile;
894 }
895
896 protected void destroyReceiver(UMOMessageReceiver receiver, UMOEndpoint endpoint) throws Exception
897 {
898 receiver.dispose();
899 }
900
901 protected abstract void doInitialise() throws InitialisationException;
902
903
904
905
906 protected abstract void doDispose();
907
908
909
910
911
912
913 protected abstract void doStart() throws UMOException;
914
915
916
917
918
919
920 protected abstract void doStop() throws UMOException;
921
922
923
924
925
926
927 public UMOTransformer getDefaultInboundTransformer()
928 {
929 if (defaultInboundTransformer != null)
930 {
931 try
932 {
933 return (UMOTransformer) defaultInboundTransformer.clone();
934 }
935 catch (CloneNotSupportedException e)
936 {
937
938 logger.error("Failed to clone default Inbound transformer");
939 }
940 }
941
942 return null;
943 }
944
945
946
947
948
949
950
951 public void setDefaultInboundTransformer(UMOTransformer defaultInboundTransformer)
952 {
953 this.defaultInboundTransformer = defaultInboundTransformer;
954 }
955
956
957
958
959
960
961 public UMOTransformer getDefaultResponseTransformer()
962 {
963 if (defaultResponseTransformer != null)
964 {
965 try
966 {
967 return (UMOTransformer) defaultResponseTransformer.clone();
968 }
969 catch (CloneNotSupportedException e)
970 {
971
972 logger.error("Failed to clone default Outbound transformer");
973 }
974 }
975
976 return null;
977 }
978
979
980
981
982
983
984 public UMOTransformer getDefaultOutboundTransformer()
985 {
986 if (defaultOutboundTransformer != null)
987 {
988 try
989 {
990 return (UMOTransformer) defaultOutboundTransformer.clone();
991 }
992 catch (CloneNotSupportedException e)
993 {
994
995 logger.error("Failed to clone default Outbound transformer");
996 }
997 }
998
999 return null;
1000 }
1001
1002
1003
1004
1005
1006
1007
1008 public void setDefaultOutboundTransformer(UMOTransformer defaultOutboundTransformer)
1009 {
1010 this.defaultOutboundTransformer = defaultOutboundTransformer;
1011 }
1012
1013
1014
1015
1016
1017
1018
1019 public void setDefaultResponseTransformer(UMOTransformer defaultResponseTransformer)
1020 {
1021 this.defaultResponseTransformer = defaultResponseTransformer;
1022 }
1023
1024
1025
1026
1027
1028
1029 public ReplyToHandler getReplyToHandler()
1030 {
1031 return new DefaultReplyToHandler(defaultResponseTransformer);
1032 }
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045 public void fireNotification(UMOServerNotification notification)
1046 {
1047 MuleManager.getInstance().fireNotification(notification);
1048 }
1049
1050
1051
1052
1053
1054
1055 public ConnectionStrategy getConnectionStrategy()
1056 {
1057
1058
1059
1060 try
1061 {
1062 return (ConnectionStrategy) BeanUtils.cloneBean(connectionStrategy);
1063 }
1064 catch (Exception e)
1065 {
1066 throw new MuleRuntimeException(CoreMessages.failedToClone("connectionStrategy"), e);
1067 }
1068 }
1069
1070
1071
1072
1073
1074
1075 public void setConnectionStrategy(ConnectionStrategy connectionStrategy)
1076 {
1077 this.connectionStrategy = connectionStrategy;
1078 }
1079
1080
1081 public boolean isDisposing()
1082 {
1083 return disposing.get();
1084 }
1085
1086
1087 public boolean isRemoteSyncEnabled()
1088 {
1089 return false;
1090 }
1091
1092 public UMOMessageReceiver getReceiver(UMOComponent component, UMOEndpoint endpoint)
1093 {
1094 return (UMOMessageReceiver) receivers.get(this.getReceiverKey(component, endpoint));
1095 }
1096
1097
1098
1099
1100
1101
1102 public Map getReceivers()
1103 {
1104 return Collections.unmodifiableMap(receivers);
1105 }
1106
1107 public UMOMessageReceiver lookupReceiver(String key)
1108 {
1109 if (key != null)
1110 {
1111 return (UMOMessageReceiver) receivers.get(key);
1112 }
1113 else
1114 {
1115 throw new IllegalArgumentException("Receiver key must not be null");
1116 }
1117 }
1118
1119 public UMOMessageReceiver[] getReceivers(String wildcardExpression)
1120 {
1121 WildcardFilter filter = new WildcardFilter(wildcardExpression);
1122 filter.setCaseSensitive(false);
1123
1124 List found = new ArrayList();
1125
1126 for (Iterator iterator = receivers.entrySet().iterator(); iterator.hasNext();)
1127 {
1128 Map.Entry e = (Map.Entry) iterator.next();
1129 if (filter.accept(e.getKey()))
1130 {
1131 found.add(e.getValue());
1132 }
1133 }
1134
1135 return (UMOMessageReceiver[]) CollectionUtils.toArrayOfComponentType(found,
1136 UMOMessageReceiver.class);
1137 }
1138
1139
1140 public void connect() throws Exception
1141 {
1142 this.checkDisposed();
1143
1144 if (connected.get())
1145 {
1146 return;
1147 }
1148
1149
1150
1151
1152
1153
1154
1155 try
1156 {
1157 if (connecting.get())
1158 {
1159 this.doConnect();
1160 }
1161
1162 if (connecting.compareAndSet(false, true))
1163 {
1164 if (logger.isDebugEnabled())
1165 {
1166 logger.debug("Connecting: " + this);
1167 }
1168
1169 connectionStrategy.connect(this);
1170
1171 logger.info("Connected: " + getConnectionDescription());
1172
1173
1174 return;
1175 }
1176
1177
1178
1179
1180 connected.set(true);
1181 connecting.set(false);
1182
1183 this.fireNotification(new ConnectionNotification(this, getConnectEventId(),
1184 ConnectionNotification.CONNECTION_CONNECTED));
1185 }
1186 catch (Exception e)
1187 {
1188 connected.set(false);
1189 connecting.set(false);
1190
1191 this.fireNotification(new ConnectionNotification(this, getConnectEventId(),
1192 ConnectionNotification.CONNECTION_FAILED));
1193
1194 if (e instanceof ConnectException || e instanceof FatalConnectException)
1195 {
1196
1197 throw e;
1198 }
1199 else
1200 {
1201 throw new ConnectException(e, this);
1202 }
1203 }
1204
1205 if (startOnConnect.get())
1206 {
1207 this.startConnector();
1208 }
1209 else
1210 {
1211 for (Iterator iterator = receivers.values().iterator(); iterator.hasNext();)
1212 {
1213 UMOMessageReceiver receiver = (UMOMessageReceiver) iterator.next();
1214 if (logger.isDebugEnabled())
1215 {
1216 logger.debug("Connecting receiver on endpoint: "
1217 + receiver.getEndpoint().getEndpointURI());
1218 }
1219 receiver.connect();
1220 }
1221 }
1222 }
1223
1224
1225 public void disconnect() throws Exception
1226 {
1227 startOnConnect.set(this.isStarted());
1228
1229 this.fireNotification(new ConnectionNotification(this, getConnectEventId(),
1230 ConnectionNotification.CONNECTION_DISCONNECTED));
1231
1232 connected.set(false);
1233
1234 try
1235 {
1236 this.doDisconnect();
1237 }
1238 finally
1239 {
1240 this.stopConnector();
1241 }
1242
1243 logger.info("Disconnected: " + this.getConnectionDescription());
1244 }
1245
1246
1247 public String getConnectionDescription()
1248 {
1249 return this.toString();
1250 }
1251
1252
1253 public final boolean isConnected()
1254 {
1255 return connected.get();
1256 }
1257
1258
1259
1260
1261
1262
1263 protected abstract void doConnect() throws Exception;
1264
1265
1266
1267
1268
1269
1270
1271 protected abstract void doDisconnect() throws Exception;
1272
1273
1274
1275
1276
1277
1278 protected String getConnectEventId()
1279 {
1280 return getName();
1281 }
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292 public boolean isCreateMultipleTransactedReceivers()
1293 {
1294 return createMultipleTransactedReceivers;
1295 }
1296
1297
1298
1299
1300
1301
1302 public void setCreateMultipleTransactedReceivers(boolean createMultipleTransactedReceivers)
1303 {
1304 this.createMultipleTransactedReceivers = createMultipleTransactedReceivers;
1305 }
1306
1307
1308
1309
1310
1311
1312
1313 public int getNumberOfConcurrentTransactedReceivers()
1314 {
1315 return numberOfConcurrentTransactedReceivers;
1316 }
1317
1318
1319
1320
1321
1322 public void setNumberOfConcurrentTransactedReceivers(int count)
1323 {
1324 numberOfConcurrentTransactedReceivers = count;
1325 }
1326
1327
1328
1329
1330
1331 public boolean isEnableMessageEvents()
1332 {
1333 return enableMessageEvents;
1334 }
1335
1336
1337
1338
1339
1340
1341
1342 public void setEnableMessageEvents(boolean enableMessageEvents)
1343 {
1344 this.enableMessageEvents = enableMessageEvents;
1345 }
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357 public void registerSupportedProtocol(String protocol)
1358 {
1359 protocol = protocol.toLowerCase();
1360 if (protocol.startsWith(getProtocol().toLowerCase()))
1361 {
1362 registerSupportedProtocolWithoutPrefix(protocol);
1363 }
1364 else
1365 {
1366 supportedProtocols.add(getProtocol().toLowerCase() + ":" + protocol);
1367 }
1368 }
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382 protected void registerSupportedProtocolWithoutPrefix(String protocol)
1383 {
1384 supportedProtocols.add(protocol.toLowerCase());
1385 }
1386
1387 public void unregisterSupportedProtocol(String protocol)
1388 {
1389 protocol = protocol.toLowerCase();
1390 if (protocol.startsWith(getProtocol().toLowerCase()))
1391 {
1392 supportedProtocols.remove(protocol);
1393 }
1394 else
1395 {
1396 supportedProtocols.remove(getProtocol().toLowerCase() + ":" + protocol);
1397 }
1398 }
1399
1400
1401
1402
1403 public boolean supportsProtocol(String protocol)
1404 {
1405 return supportedProtocols.contains(protocol.toLowerCase());
1406 }
1407
1408
1409
1410
1411
1412
1413 public List getSupportedProtocols()
1414 {
1415 return Collections.unmodifiableList(supportedProtocols);
1416 }
1417
1418
1419
1420
1421
1422
1423 public void setSupportedProtocols(List supportedProtocols)
1424 {
1425 for (Iterator iterator = supportedProtocols.iterator(); iterator.hasNext();)
1426 {
1427 String s = (String) iterator.next();
1428 registerSupportedProtocol(s);
1429 }
1430 }
1431
1432
1433
1434
1435 protected UMOWorkManager getReceiverWorkManager(String receiverName) throws UMOException
1436 {
1437
1438 if (receiverWorkManager.get() == null)
1439 {
1440 UMOWorkManager newWorkManager = this.getReceiverThreadingProfile().createWorkManager(
1441 this.getName() + '.' + receiverName);
1442
1443 if (receiverWorkManager.compareAndSet(null, newWorkManager))
1444 {
1445 newWorkManager.start();
1446 }
1447 }
1448
1449 return (UMOWorkManager) receiverWorkManager.get();
1450 }
1451
1452
1453
1454
1455
1456
1457 protected UMOWorkManager getDispatcherWorkManager() throws UMOException
1458 {
1459
1460 if (dispatcherWorkManager.get() == null)
1461 {
1462 UMOWorkManager newWorkManager = this.getDispatcherThreadingProfile().createWorkManager(
1463 getName() + ".dispatcher");
1464
1465 if (dispatcherWorkManager.compareAndSet(null, newWorkManager))
1466 {
1467 newWorkManager.start();
1468 }
1469 }
1470
1471 return (UMOWorkManager) dispatcherWorkManager.get();
1472 }
1473
1474
1475 public ScheduledExecutorService getScheduler()
1476 {
1477 if (scheduler.get() == null)
1478 {
1479 ThreadFactory threadFactory = new NamedThreadFactory(this.getName() + ".scheduler");
1480 ScheduledThreadPoolExecutor newExecutor = new ScheduledThreadPoolExecutor(4, threadFactory);
1481 newExecutor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
1482 newExecutor.setKeepAliveTime(this.getReceiverThreadingProfile().getThreadTTL(),
1483 TimeUnit.MILLISECONDS);
1484 newExecutor.allowCoreThreadTimeOut(true);
1485
1486 if (!scheduler.compareAndSet(null, newExecutor))
1487 {
1488
1489 newExecutor.shutdown();
1490 }
1491 }
1492
1493 return (ScheduledExecutorService) scheduler.get();
1494 }
1495
1496
1497
1498
1499
1500
1501 public UMOSessionHandler getSessionHandler()
1502 {
1503 return sessionHandler;
1504 }
1505
1506
1507
1508
1509
1510
1511 public void setSessionHandler(UMOSessionHandler sessionHandler)
1512 {
1513 this.sessionHandler = sessionHandler;
1514 }
1515
1516
1517 public void workAccepted(WorkEvent event)
1518 {
1519 this.handleWorkException(event, "workAccepted");
1520 }
1521
1522
1523 public void workRejected(WorkEvent event)
1524 {
1525 this.handleWorkException(event, "workRejected");
1526 }
1527
1528
1529 public void workStarted(WorkEvent event)
1530 {
1531 this.handleWorkException(event, "workStarted");
1532 }
1533
1534
1535 public void workCompleted(WorkEvent event)
1536 {
1537 this.handleWorkException(event, "workCompleted");
1538 }
1539
1540 protected void handleWorkException(WorkEvent event, String type)
1541 {
1542 if (event == null)
1543 {
1544 return;
1545 }
1546
1547 Throwable e = event.getException();
1548
1549 if (e == null)
1550 {
1551 return;
1552 }
1553
1554 if (e.getCause() != null)
1555 {
1556 e = e.getCause();
1557 }
1558
1559 logger.error("Work caused exception on '" + type + "'. Work being executed was: "
1560 + event.getWork().toString());
1561
1562 if (e instanceof Exception)
1563 {
1564 this.handleException((Exception) e);
1565 }
1566 else
1567 {
1568 throw new MuleRuntimeException(CoreMessages.connectorCausedError(this.getName()), e);
1569 }
1570 }
1571
1572
1573
1574
1575
1576 public void dispatch(UMOImmutableEndpoint endpoint, UMOEvent event) throws DispatchException
1577 {
1578 UMOMessageDispatcher dispatcher = null;
1579
1580 try
1581 {
1582 dispatcher = this.getDispatcher(endpoint);
1583 dispatcher.dispatch(event);
1584 }
1585 catch (DispatchException dex)
1586 {
1587 throw dex;
1588 }
1589 catch (UMOException ex)
1590 {
1591 throw new DispatchException(event.getMessage(), endpoint, ex);
1592 }
1593 finally
1594 {
1595 this.returnDispatcher(endpoint, dispatcher);
1596 }
1597 }
1598
1599
1600 public UMOMessage receive(UMOEndpointURI endpointUri, long timeout) throws Exception
1601 {
1602 return this.receive(new ImmutableMuleEndpoint(endpointUri.toString(), true), timeout);
1603 }
1604
1605
1606 public UMOMessage receive(UMOImmutableEndpoint endpoint, long timeout) throws Exception
1607 {
1608 UMOMessageDispatcher dispatcher = null;
1609
1610 try
1611 {
1612 dispatcher = this.getDispatcher(endpoint);
1613 return dispatcher.receive(timeout);
1614 }
1615 finally
1616 {
1617 this.returnDispatcher(endpoint, dispatcher);
1618 }
1619 }
1620
1621
1622 public UMOMessage send(UMOImmutableEndpoint endpoint, UMOEvent event) throws DispatchException
1623 {
1624 UMOMessageDispatcher dispatcher = null;
1625
1626 try
1627 {
1628 dispatcher = this.getDispatcher(endpoint);
1629 return dispatcher.send(event);
1630 }
1631 catch (DispatchException dex)
1632 {
1633 throw dex;
1634 }
1635 catch (UMOException ex)
1636 {
1637 throw new DispatchException(event.getMessage(), endpoint, ex);
1638 }
1639 finally
1640 {
1641 this.returnDispatcher(endpoint, dispatcher);
1642 }
1643 }
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659 public void initialiseFromUrl(UMOEndpointURI endpointUri) throws InitialisationException
1660 {
1661 if (!supportsProtocol(endpointUri.getFullScheme()))
1662 {
1663 throw new InitialisationException(
1664 CoreMessages.schemeNotCompatibleWithConnector(endpointUri.getFullScheme(),
1665 this.getClass()), this);
1666 }
1667 Properties props = new Properties();
1668 props.putAll(endpointUri.getParams());
1669
1670 if (endpointUri.getUserInfo() != null)
1671 {
1672 props.setProperty("username", endpointUri.getUsername());
1673 String passwd = endpointUri.getPassword();
1674 if (passwd != null)
1675 {
1676 props.setProperty("password", passwd);
1677 }
1678 }
1679 String host = endpointUri.getHost();
1680 if (host != null)
1681 {
1682 props.setProperty("hostname", host);
1683 props.setProperty("host", host);
1684 }
1685 if (endpointUri.getPort() > -1)
1686 {
1687 props.setProperty("port", String.valueOf(endpointUri.getPort()));
1688 }
1689
1690 org.mule.util.BeanUtils.populateWithoutFail(this, props, true);
1691
1692 setName(ObjectNameHelper.getConnectorName(this));
1693 }
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703 protected synchronized void initFromServiceDescriptor() throws InitialisationException
1704 {
1705 try
1706 {
1707 serviceDescriptor = TransportFactory.getServiceDescriptor(getProtocol().toLowerCase(),
1708 serviceOverrides);
1709
1710 if (serviceDescriptor.getDispatcherFactory() != null)
1711 {
1712 logger.debug("Loading DispatcherFactory: " + serviceDescriptor.getDispatcherFactory());
1713 this.setDispatcherFactory(serviceDescriptor.createDispatcherFactory());
1714 }
1715
1716 defaultInboundTransformer = serviceDescriptor.createInboundTransformer();
1717 defaultOutboundTransformer = serviceDescriptor.createOutboundTransformer();
1718 defaultResponseTransformer = serviceDescriptor.createResponseTransformer();
1719
1720 sessionHandler = serviceDescriptor.createSessionHandler();
1721
1722
1723
1724
1725
1726 Map props = new HashMap();
1727 PropertiesUtils.getPropertiesWithPrefix(MuleManager.getInstance().getProperties(), getProtocol()
1728 .toLowerCase(), props);
1729 if (props.size() > 0)
1730 {
1731 props = PropertiesUtils.removeNamespaces(props);
1732 org.mule.util.BeanUtils.populateWithoutFail(this, props, true);
1733 }
1734 }
1735 catch (Exception e)
1736 {
1737 throw new InitialisationException(e, this);
1738 }
1739 }
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749 protected TransportServiceDescriptor getServiceDescriptor()
1750 {
1751 if (serviceDescriptor == null)
1752 {
1753 throw new IllegalStateException("This connector has not yet been initialised: " + name);
1754 }
1755 return serviceDescriptor;
1756 }
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771 protected UMOMessageReceiver createReceiver(UMOComponent component, UMOEndpoint endpoint)
1772 throws Exception
1773 {
1774 return getServiceDescriptor().createMessageReceiver(this, component, endpoint);
1775 }
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788 public UMOMessageAdapter getMessageAdapter(Object message) throws MessagingException
1789 {
1790 try
1791 {
1792 return serviceDescriptor.createMessageAdapter(message);
1793 }
1794 catch (TransportServiceException e)
1795 {
1796 throw new MessagingException(CoreMessages.failedToCreate("Message Adapter"),
1797 message, e);
1798 }
1799 }
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812 public UMOStreamMessageAdapter getStreamMessageAdapter(InputStream in, OutputStream out)
1813 throws MessagingException
1814 {
1815 try
1816 {
1817 return serviceDescriptor.createStreamMessageAdapter(in, out);
1818 }
1819 catch (TransportServiceException e)
1820 {
1821 throw new MessagingException(CoreMessages.failedToCreate("Stream Message Adapter"),
1822 in, e);
1823 }
1824 }
1825
1826
1827
1828
1829
1830
1831
1832 public Map getServiceOverrides()
1833 {
1834 return serviceOverrides;
1835 }
1836
1837
1838
1839
1840
1841
1842 public void setServiceOverrides(Map serviceOverrides)
1843 {
1844 this.serviceOverrides = new Properties();
1845 this.serviceOverrides.putAll(serviceOverrides);
1846 }
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860 public OutputStream getOutputStream(UMOImmutableEndpoint endpoint, UMOMessage message)
1861 throws UMOException
1862 {
1863 throw new UnsupportedOperationException(
1864 CoreMessages.streamingNotSupported(this.getProtocol()).toString());
1865 }
1866
1867
1868 public String toString()
1869 {
1870 final StringBuffer sb = new StringBuffer(120);
1871 sb.append(ClassUtils.getSimpleName(this.getClass()));
1872 sb.append("{this=").append(Integer.toHexString(System.identityHashCode(this)));
1873 sb.append(", started=").append(started);
1874 sb.append(", initialised=").append(initialised);
1875 sb.append(", name='").append(name).append('\'');
1876 sb.append(", disposed=").append(disposed);
1877 sb.append(", numberOfConcurrentTransactedReceivers=").append(numberOfConcurrentTransactedReceivers);
1878 sb.append(", createMultipleTransactedReceivers=").append(createMultipleTransactedReceivers);
1879 sb.append(", connected=").append(connected);
1880 sb.append(", supportedProtocols=").append(supportedProtocols);
1881 sb.append(", serviceOverrides=").append(serviceOverrides);
1882 sb.append('}');
1883 return sb.toString();
1884 }
1885 }