2121import java .net .InetAddress ;
2222import java .net .SocketException ;
2323import java .net .SocketTimeoutException ;
24+ import java .util .Collection ;
2425import java .util .Collections ;
2526import java .util .HashMap ;
2627import java .util .Map ;
28+ import java .util .concurrent .CopyOnWriteArrayList ;
2729import java .util .concurrent .ExecutorService ;
2830import java .util .concurrent .TimeoutException ;
2931
3032import com .rabbitmq .client .AMQP ;
33+ import com .rabbitmq .client .AuthenticationFailureException ;
34+ import com .rabbitmq .client .BlockedListener ;
3135import com .rabbitmq .client .Method ;
3236import com .rabbitmq .client .AlreadyClosedException ;
3337import com .rabbitmq .client .Channel ;
@@ -81,6 +85,8 @@ public static final Map<String, Object> defaultClientProperties() {
8185 capabilities .put ("exchange_exchange_bindings" , true );
8286 capabilities .put ("basic.nack" , true );
8387 capabilities .put ("consumer_cancel_notify" , true );
88+ capabilities .put ("connection.blocked" , true );
89+ capabilities .put ("authentication_failure_close" , true );
8490
8591 props .put ("capabilities" , capabilities );
8692
@@ -130,6 +136,7 @@ public static final Map<String, Object> defaultClientProperties() {
130136 private final int requestedFrameMax ;
131137 private final String username ;
132138 private final String password ;
139+ private final Collection <BlockedListener > blockedListeners = new CopyOnWriteArrayList <BlockedListener >();
133140
134141 /* State modified after start - all volatile */
135142
@@ -274,9 +281,10 @@ public AMQConnection(String username,
274281 * either before, or during, protocol negotiation;
275282 * sub-classes {@link ProtocolVersionMismatchException} and
276283 * {@link PossibleAuthenticationFailureException} will be thrown in the
277- * corresponding circumstances. If an exception is thrown, connection
278- * resources allocated can all be garbage collected when the connection
279- * object is no longer referenced.
284+ * corresponding circumstances. {@link AuthenticationFailureException}
285+ * will be thrown if the broker closes the connection with ACCESS_REFUSED.
286+ * If an exception is thrown, connection resources allocated can all be
287+ * garbage collected when the connection object is no longer referenced.
280288 */
281289 public void start ()
282290 throws IOException
@@ -352,6 +360,16 @@ public void start()
352360 response = sm .handleChallenge (challenge , this .username , this .password );
353361 }
354362 } catch (ShutdownSignalException e ) {
363+ Object shutdownReason = e .getReason ();
364+ if (shutdownReason instanceof AMQCommand ) {
365+ Method shutdownMethod = ((AMQCommand ) shutdownReason ).getMethod ();
366+ if (shutdownMethod instanceof AMQP .Connection .Close ) {
367+ AMQP .Connection .Close shutdownClose = (AMQP .Connection .Close ) shutdownMethod ;
368+ if (shutdownClose .getReplyCode () == AMQP .ACCESS_REFUSED ) {
369+ throw new AuthenticationFailureException (shutdownClose .getReplyText ());
370+ }
371+ }
372+ }
355373 throw new PossibleAuthenticationFailureException (e );
356374 }
357375 } while (connTune == null );
@@ -597,6 +615,25 @@ public boolean processControlCommand(Command c) throws IOException
597615 if (method instanceof AMQP .Connection .Close ) {
598616 handleConnectionClose (c );
599617 return true ;
618+ } else if (method instanceof AMQP .Connection .Blocked ) {
619+ AMQP .Connection .Blocked blocked = (AMQP .Connection .Blocked ) method ;
620+ try {
621+ for (BlockedListener l : this .blockedListeners ) {
622+ l .handleBlocked (blocked .getReason ());
623+ }
624+ } catch (Throwable ex ) {
625+ getExceptionHandler ().handleBlockedListenerException (this , ex );
626+ }
627+ return true ;
628+ } else if (method instanceof AMQP .Connection .Unblocked ) {
629+ try {
630+ for (BlockedListener l : this .blockedListeners ) {
631+ l .handleUnblocked ();
632+ }
633+ } catch (Throwable ex ) {
634+ getExceptionHandler ().handleBlockedListenerException (this , ex );
635+ }
636+ return true ;
600637 } else {
601638 return false ;
602639 }
@@ -621,7 +658,7 @@ public boolean processControlCommand(Command c) throws IOException
621658 }
622659
623660 public void handleConnectionClose (Command closeCommand ) {
624- ShutdownSignalException sse = shutdown (closeCommand , false , null , false );
661+ ShutdownSignalException sse = shutdown (closeCommand , false , null , _inConnectionNegotiation );
625662 try {
626663 _channel0 .quiescingTransmit (new AMQP .Connection .CloseOk .Builder ().build ());
627664 } catch (IOException _) { } // ignore
@@ -823,4 +860,16 @@ public AMQCommand transformReply(AMQCommand command) {
823860 private String getHostAddress () {
824861 return getAddress () == null ? null : getAddress ().getHostAddress ();
825862 }
863+
864+ public void addBlockedListener (BlockedListener listener ) {
865+ blockedListeners .add (listener );
866+ }
867+
868+ public boolean removeBlockedListener (BlockedListener listener ) {
869+ return blockedListeners .remove (listener );
870+ }
871+
872+ public void clearBlockedListeners () {
873+ blockedListeners .clear ();
874+ }
826875}
0 commit comments