1818package com .rabbitmq .client .impl ;
1919
2020import java .io .IOException ;
21+ import java .util .Collection ;
2122import java .util .Collections ;
2223import java .util .HashMap ;
2324import java .util .Map ;
25+ import java .util .concurrent .CopyOnWriteArrayList ;
2426import java .util .concurrent .TimeoutException ;
2527
2628import com .rabbitmq .client .AMQP ;
@@ -78,25 +80,18 @@ public class ChannelN extends AMQChannel implements com.rabbitmq.client.Channel
7880 public final Map <String , Consumer > _consumers =
7981 Collections .synchronizedMap (new HashMap <String , Consumer >());
8082
81- /** Reference to the currently-active ReturnListener, or null if there is none.
82- */
83- public volatile ReturnListener returnListener = null ;
84-
85- /** Reference to the currently-active FlowListener, or null if there is none.
86- */
87- public volatile FlowListener flowListener = null ;
83+ /* All listeners collections are in CopyOnWriteArrayList objects */
84+ /** The ReturnListener collection. */
85+ private final Collection < ReturnListener > returnListeners = new CopyOnWriteArrayList < ReturnListener >() ;
86+ /** The FlowListener collection. */
87+ private final Collection < FlowListener > flowListeners = new CopyOnWriteArrayList < FlowListener >();
88+ /** The ConfirmListener collection. */
89+ private final Collection < ConfirmListener > confirmListeners = new CopyOnWriteArrayList < ConfirmListener >() ;
8890
89- /** Reference to the currently-active ConfirmListener, or null if there is none.
90- */
91- public volatile ConfirmListener confirmListener = null ;
92-
93- /** Sequence number of next published message requiring confirmation.
94- */
91+ /** Sequence number of next published message requiring confirmation. */
9592 private long nextPublishSeqNo = 0L ;
9693
97- /** Reference to the currently-active default consumer, or null if there is
98- * none.
99- */
94+ /** The current default consumer, or null if there is none. */
10095 public volatile Consumer defaultConsumer = null ;
10196
10297 /**
@@ -123,43 +118,40 @@ public void open() throws IOException {
123118 Utility .use (openOk );
124119 }
125120
126- /** Returns the current ReturnListener. */
127- public ReturnListener getReturnListener () {
128- return returnListener ;
121+ public void addReturnListener (ReturnListener listener ) {
122+ returnListeners .add (listener );
129123 }
130124
131- /**
132- * Sets the current ReturnListener.
133- * A null argument is interpreted to mean "do not use a return listener".
134- */
135- public void setReturnListener (ReturnListener listener ) {
136- returnListener = listener ;
125+ public boolean removeReturnListener (ReturnListener listener ) {
126+ return returnListeners .remove (listener );
137127 }
138128
139- /** Returns the current {@link FlowListener}. */
140- public FlowListener getFlowListener () {
141- return flowListener ;
129+ public void clearReturnListeners () {
130+ returnListeners .clear ();
142131 }
143132
144- /**
145- * Sets the current {@link FlowListener}.
146- * A null argument is interpreted to mean "do not use a flow listener".
147- */
148- public void setFlowListener (FlowListener listener ) {
149- flowListener = listener ;
133+ public void addFlowListener (FlowListener listener ) {
134+ flowListeners .add (listener );
150135 }
151136
152- /** Returns the current {@link ConfirmListener}. */
153- public ConfirmListener getConfirmListener () {
154- return confirmListener ;
137+ public boolean removeFlowListener (FlowListener listener ) {
138+ return flowListeners .remove (listener );
155139 }
156140
157- /**
158- * Sets the current {@link ConfirmListener}.
159- * A null argument is interpreted to mean "do not use a confirm listener".
160- */
161- public void setConfirmListener (ConfirmListener listener ) {
162- confirmListener = listener ;
141+ public void clearFlowListeners () {
142+ flowListeners .clear ();
143+ }
144+
145+ public void addConfirmListener (ConfirmListener listener ) {
146+ confirmListeners .add (listener );
147+ }
148+
149+ public boolean removeConfirmListener (ConfirmListener listener ) {
150+ return confirmListeners .remove (listener );
151+ }
152+
153+ public void clearConfirmListeners () {
154+ confirmListeners .clear ();
163155 }
164156
165157 /** Returns the current default consumer. */
@@ -275,22 +267,7 @@ public void releaseChannelNumber() {
275267 }
276268 return true ;
277269 } else if (method instanceof Basic .Return ) {
278- ReturnListener l = getReturnListener ();
279- if (l != null ) {
280- Basic .Return basicReturn = (Basic .Return ) method ;
281- try {
282- l .handleReturn (basicReturn .getReplyCode (),
283- basicReturn .getReplyText (),
284- basicReturn .getExchange (),
285- basicReturn .getRoutingKey (),
286- (BasicProperties )
287- command .getContentHeader (),
288- command .getContentBody ());
289- } catch (Throwable ex ) {
290- _connection .getExceptionHandler ().handleReturnListenerException (this ,
291- ex );
292- }
293- }
270+ callReturnListeners (command , (Basic .Return ) method );
294271 return true ;
295272 } else if (method instanceof Channel .Flow ) {
296273 Channel .Flow channelFlow = (Channel .Flow ) method ;
@@ -299,36 +276,13 @@ public void releaseChannelNumber() {
299276 transmit (new Channel .FlowOk (!_blockContent ));
300277 _channelMutex .notifyAll ();
301278 }
302- FlowListener l = getFlowListener ();
303- if (l != null ) {
304- try {
305- l .handleFlow (channelFlow .getActive ());
306- } catch (Throwable ex ) {
307- _connection .getExceptionHandler ().handleFlowListenerException (this , ex );
308- }
309- }
279+ callFlowListeners (command , channelFlow );
310280 return true ;
311281 } else if (method instanceof Basic .Ack ) {
312- Basic .Ack ack = (Basic .Ack ) method ;
313- ConfirmListener l = getConfirmListener ();
314- if (l != null ) {
315- try {
316- l .handleAck (ack .getDeliveryTag (), ack .getMultiple ());
317- } catch (Throwable ex ) {
318- _connection .getExceptionHandler ().handleConfirmListenerException (this , ex );
319- }
320- }
282+ callConfirmListeners (command , (Basic .Ack ) method );
321283 return true ;
322284 } else if (method instanceof Basic .Nack ) {
323- Basic .Nack nack = (Basic .Nack ) method ;
324- ConfirmListener l = getConfirmListener ();
325- if (l != null ) {
326- try {
327- l .handleNack (nack .getDeliveryTag (), nack .getMultiple ());
328- } catch (Throwable ex ) {
329- _connection .getExceptionHandler ().handleConfirmListenerException (this , ex );
330- }
331- }
285+ callConfirmListeners (command , (Basic .Nack ) method );
332286 return true ;
333287 } else if (method instanceof Basic .RecoverOk ) {
334288 for (Consumer callback : _consumers .values ()) {
@@ -379,6 +333,51 @@ public void releaseChannelNumber() {
379333 }
380334 }
381335
336+ private void callReturnListeners (Command command , Basic .Return basicReturn ) {
337+ try {
338+ for (ReturnListener l : this .returnListeners ) {
339+ l .handleReturn (basicReturn .getReplyCode (),
340+ basicReturn .getReplyText (),
341+ basicReturn .getExchange (),
342+ basicReturn .getRoutingKey (),
343+ (BasicProperties ) command .getContentHeader (),
344+ command .getContentBody ());
345+ }
346+ } catch (Throwable ex ) {
347+ _connection .getExceptionHandler ().handleReturnListenerException (this , ex );
348+ }
349+ }
350+
351+ private void callFlowListeners (Command command , Channel .Flow channelFlow ) {
352+ try {
353+ for (FlowListener l : this .flowListeners ) {
354+ l .handleFlow (channelFlow .getActive ());
355+ }
356+ } catch (Throwable ex ) {
357+ _connection .getExceptionHandler ().handleFlowListenerException (this , ex );
358+ }
359+ }
360+
361+ private void callConfirmListeners (Command command , Basic .Ack ack ) {
362+ try {
363+ for (ConfirmListener l : this .confirmListeners ) {
364+ l .handleAck (ack .getDeliveryTag (), ack .getMultiple ());
365+ }
366+ } catch (Throwable ex ) {
367+ _connection .getExceptionHandler ().handleConfirmListenerException (this , ex );
368+ }
369+ }
370+
371+ private void callConfirmListeners (Command command , Basic .Nack nack ) {
372+ try {
373+ for (ConfirmListener l : this .confirmListeners ) {
374+ l .handleNack (nack .getDeliveryTag (), nack .getMultiple ());
375+ }
376+ } catch (Throwable ex ) {
377+ _connection .getExceptionHandler ().handleConfirmListenerException (this , ex );
378+ }
379+ }
380+
382381 private void asyncShutdown (Command command ) throws IOException {
383382 releaseChannelNumber ();
384383 ShutdownSignalException signal = new ShutdownSignalException (false ,
0 commit comments