ConnectionCloseMethodHandler.java
001 /*
002  *
003  * Licensed to the Apache Software Foundation (ASF) under one
004  * or more contributor license agreements.  See the NOTICE file
005  * distributed with this work for additional information
006  * regarding copyright ownership.  The ASF licenses this file
007  * to you under the Apache License, Version 2.0 (the
008  * "License"); you may not use this file except in compliance
009  * with the License.  You may obtain a copy of the License at
010  *
011  *   http://www.apache.org/licenses/LICENSE-2.0
012  *
013  * Unless required by applicable law or agreed to in writing,
014  * software distributed under the License is distributed on an
015  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016  * KIND, either express or implied.  See the License for the
017  * specific language governing permissions and limitations
018  * under the License.
019  *
020  */
021 package org.apache.qpid.client.handler;
022 
023 import org.apache.qpid.AMQConnectionClosedException;
024 import org.apache.qpid.AMQException;
025 import org.apache.qpid.client.AMQAuthenticationException;
026 import org.apache.qpid.client.protocol.AMQProtocolSession;
027 import org.apache.qpid.client.state.AMQState;
028 import org.apache.qpid.client.state.StateAwareMethodListener;
029 import org.apache.qpid.framing.AMQShortString;
030 import org.apache.qpid.framing.ConnectionCloseBody;
031 import org.apache.qpid.framing.ConnectionCloseOkBody;
032 import org.apache.qpid.protocol.AMQConstant;
033 
034 import org.slf4j.Logger;
035 import org.slf4j.LoggerFactory;
036 
037 public class ConnectionCloseMethodHandler implements StateAwareMethodListener<ConnectionCloseBody>
038 {
039     private static final Logger _logger = LoggerFactory.getLogger(ConnectionCloseMethodHandler.class);
040 
041     private static ConnectionCloseMethodHandler _handler = new ConnectionCloseMethodHandler();
042 
043     public static ConnectionCloseMethodHandler getInstance()
044     {
045         return _handler;
046     }
047 
048     private ConnectionCloseMethodHandler()
049     {
050     }
051 
052     public void methodReceived(AMQProtocolSession session, ConnectionCloseBody method, int channelId)
053             throws AMQException
054     {
055         _logger.info("ConnectionClose frame received");
056 
057         // does it matter
058         // stateManager.changeState(AMQState.CONNECTION_CLOSING);
059 
060         AMQConstant errorCode = AMQConstant.getConstant(method.getReplyCode());
061         AMQShortString reason = method.getReplyText();
062 
063         AMQException error = null;
064 
065         try
066         {
067 
068             ConnectionCloseOkBody closeOkBody = session.getMethodRegistry().createConnectionCloseOkBody();
069             // TODO: check whether channel id of zero is appropriate
070             // Be aware of possible changes to parameter order as versions change.
071             session.writeFrame(closeOkBody.generateFrame(0));
072 
073             if (errorCode != AMQConstant.REPLY_SUCCESS)
074             {
075                 if (errorCode == AMQConstant.NOT_ALLOWED || (errorCode == AMQConstant.ACCESS_REFUSED))
076                 {
077                     _logger.info("Error :" + errorCode + ":" + Thread.currentThread().getName());
078 
079                     error = new AMQAuthenticationException(errorCode, reason == null null : reason.toString()null);
080                 }
081                 else
082                 {
083                     _logger.info("Connection close received with error code " + errorCode);
084 
085                     error = new AMQConnectionClosedException(errorCode, "Error: " + reason, null);
086                 }
087             }
088         }
089         finally
090         {
091 
092             if (error != null)
093             {
094                 session.notifyError(error);
095             }            
096 
097             // Close the protocol Session, including any open TCP connections 
098             session.closeProtocolSession();
099 
100             // Closing the session should not introduce a race condition as this thread will continue to propgate any
101             // exception in to the exceptionCaught method of the SessionHandler.
102             // Any sessionClosed event should occur after this.
103         }
104     }
105 
106 }