|
37 | 37 | import com.rabbitmq.client.Connection; |
38 | 38 | import com.rabbitmq.client.Consumer; |
39 | 39 | import com.rabbitmq.client.Envelope; |
| 40 | +import com.rabbitmq.client.FlowListener; |
40 | 41 | import com.rabbitmq.client.GetResponse; |
41 | 42 | import com.rabbitmq.client.MessageProperties; |
42 | 43 | import com.rabbitmq.client.ReturnListener; |
@@ -93,6 +94,15 @@ public class ChannelN extends AMQChannel implements com.rabbitmq.client.Channel |
93 | 94 | */ |
94 | 95 | public volatile ReturnListener returnListener = null; |
95 | 96 |
|
| 97 | + /** Reference to the currently-active FlowListener, or null if there is none. |
| 98 | + */ |
| 99 | + public volatile FlowListener flowListener = null; |
| 100 | + |
| 101 | + /** Reference to the currently-active default consumer, or null if there is |
| 102 | + * none. |
| 103 | + */ |
| 104 | + public volatile Consumer defaultConsumer = null; |
| 105 | + |
96 | 106 | /** |
97 | 107 | * Construct a new channel on the given connection with the given |
98 | 108 | * channel number. Usually not called directly - call |
@@ -130,6 +140,32 @@ public void setReturnListener(ReturnListener listener) { |
130 | 140 | returnListener = listener; |
131 | 141 | } |
132 | 142 |
|
| 143 | + /** Returns the current FlowListener. */ |
| 144 | + public FlowListener getFlowListener() { |
| 145 | + return flowListener; |
| 146 | + } |
| 147 | + |
| 148 | + /** |
| 149 | + * Sets the current FlowListener. |
| 150 | + * A null argument is interpreted to mean "do not use a flow listener". |
| 151 | + */ |
| 152 | + public void setFlowListener(FlowListener listener) { |
| 153 | + flowListener = listener; |
| 154 | + } |
| 155 | + |
| 156 | + /** Returns the current default consumer. */ |
| 157 | + public Consumer getDefaultConsumer() { |
| 158 | + return defaultConsumer; |
| 159 | + } |
| 160 | + |
| 161 | + /** |
| 162 | + * Sets the current default consumer. |
| 163 | + * A null argument is interpreted to mean "do not use a default consumer". |
| 164 | + */ |
| 165 | + public void setDefaultConsumer(Consumer consumer) { |
| 166 | + defaultConsumer = consumer; |
| 167 | + } |
| 168 | + |
133 | 169 | /** |
134 | 170 | * Protected API - sends a ShutdownSignal to all active consumers. |
135 | 171 | * @param signal an exception signalling channel shutdown |
@@ -182,7 +218,7 @@ public void releaseChannelNumber() { |
182 | 218 | // If we are not, however, then we are in a quiescing, or |
183 | 219 | // shutting-down state as the result of an application |
184 | 220 | // decision to close this channel, and we are to discard all |
185 | | - // incoming commands except for close and close-ok. |
| 221 | + // incoming commands except for a close and close-ok. |
186 | 222 |
|
187 | 223 | Method method = command.getMethod(); |
188 | 224 |
|
@@ -210,8 +246,17 @@ public void releaseChannelNumber() { |
210 | 246 |
|
211 | 247 | Consumer callback = _consumers.get(m.consumerTag); |
212 | 248 | if (callback == null) { |
213 | | - // FIXME: what to do when we get such an unsolicited delivery? |
214 | | - throw new UnsupportedOperationException("FIXME unsolicited delivery"); |
| 249 | + if (defaultConsumer == null) { |
| 250 | + // No handler set. We should blow up as this message |
| 251 | + // needs acking, just dropping it is not enough. See bug |
| 252 | + // 22587 for discussion. |
| 253 | + throw new IllegalStateException("Unsolicited delivery -" + |
| 254 | + " see Channel.setDefaultConsumer to handle this" + |
| 255 | + " case."); |
| 256 | + } |
| 257 | + else { |
| 258 | + callback = defaultConsumer; |
| 259 | + } |
215 | 260 | } |
216 | 261 |
|
217 | 262 | Envelope envelope = new Envelope(m.deliveryTag, |
@@ -256,6 +301,14 @@ public void releaseChannelNumber() { |
256 | 301 | transmit(new Channel.FlowOk(channelFlow.active)); |
257 | 302 | _channelMutex.notifyAll(); |
258 | 303 | } |
| 304 | + FlowListener l = getFlowListener(); |
| 305 | + if (l != null) { |
| 306 | + try { |
| 307 | + l.handleFlow(channelFlow.active); |
| 308 | + } catch (Throwable ex) { |
| 309 | + _connection.getExceptionHandler().handleFlowListenerException(this, ex); |
| 310 | + } |
| 311 | + } |
259 | 312 | return true; |
260 | 313 | } else if (method instanceof Basic.RecoverOk) { |
261 | 314 | for (Consumer callback: _consumers.values()) { |
@@ -686,13 +739,14 @@ public Consumer transformReply(AMQCommand replyCommand) { |
686 | 739 | } |
687 | 740 | } |
688 | 741 |
|
689 | | - /** Public API - {@inheritDoc} */ |
| 742 | + /** Public API - {@inheritDoc} */ |
690 | 743 | public Basic.RecoverOk basicRecover(boolean requeue) |
691 | 744 | throws IOException |
692 | 745 | { |
693 | 746 | return (Basic.RecoverOk) exnWrappingRpc(new Basic.Recover(requeue)).getMethod(); |
694 | 747 | } |
695 | 748 |
|
| 749 | + |
696 | 750 | /** Public API - {@inheritDoc} */ |
697 | 751 | public void basicRecoverAsync(boolean requeue) |
698 | 752 | throws IOException |
@@ -725,4 +779,10 @@ public Tx.RollbackOk txRollback() |
725 | 779 | public Channel.FlowOk flow(final boolean a) throws IOException { |
726 | 780 | return (Channel.FlowOk) exnWrappingRpc(new Channel.Flow() {{active = a;}}).getMethod(); |
727 | 781 | } |
| 782 | + |
| 783 | + /** Public API - {@inheritDoc} */ |
| 784 | + public Channel.FlowOk getFlow() { |
| 785 | + return new Channel.FlowOk(!_blockContent); |
| 786 | + } |
| 787 | + |
728 | 788 | } |
0 commit comments