/*
*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 */
package org.apache.qpid.client;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.InetAddress;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.nio.channels.UnresolvedAddressException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

import javax.jms.ConnectionConsumer;
import javax.jms.ConnectionMetaData;
import javax.jms.Destination;
import javax.jms.ExceptionListener;
import javax.jms.IllegalStateException;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageEOFException;
import javax.jms.Queue;
import javax.jms.QueueSession;
import javax.jms.ServerSessionPool;
import javax.jms.StreamMessage;
import javax.jms.Topic;
import javax.jms.TopicSession;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.naming.StringRefAddr;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.qpid.AMQConnectionFailureException;
import org.apache.qpid.AMQDisconnectedException;
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQProtocolException;
import org.apache.qpid.AMQUnresolvedAddressException;
import org.apache.qpid.QpidException;
import org.apache.qpid.client.failover.ConnectionRedirectException;
import org.apache.qpid.client.failover.FailoverException;
import org.apache.qpid.client.failover.FailoverProtectedOperation;
import org.apache.qpid.client.security.CallbackHandlerRegistry;
import org.apache.qpid.client.state.AMQState;
import org.apache.qpid.client.state.AMQStateManager;
import org.apache.qpid.client.util.ClassLoadingAwareObjectInputStream;
import org.apache.qpid.client.util.JMSExceptionHelper;
import org.apache.qpid.configuration.ClientProperties;
import org.apache.qpid.configuration.CommonProperties;
import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.framing.ProtocolVersion;
import org.apache.qpid.jms.ConnectionListener;
import org.apache.qpid.jms.ConnectionURL;
import org.apache.qpid.jms.FailoverPolicy;
import org.apache.qpid.jms.Session;
import org.apache.qpid.jndi.ObjectFactory;
import org.apache.qpid.protocol.ErrorCodes;
import org.apache.qpid.transport.ConnectionSettings;
import org.apache.qpid.url.URLSyntaxException;

public class AMQConnection extends Closeable implements CommonConnection, Referenceable,
                                                        ClassLoadingAwareObjectInputStream.TrustedClassFilter
{
    public static final String JNDI_ADDRESS_CONNECTION_URL = "connectionURL";

    private static final Logger _logger = LoggerFactory.getLogger(AMQConnection.class);

    static
    {
        ClientProperties.ensureIsLoaded();
    }

    private static final AtomicLong CONN_NUMBER_GENERATOR = new AtomicLong();
    private static final long DEFAULT_CLOSE_TIMEOUT = Long.getLong(ClientProperties.QPID_CLOSE_TIMEOUT,
                                                                   ClientProperties.DEFAULT_CLOSE_TIMEOUT);

    private final long _connectionNumber = CONN_NUMBER_GENERATOR.incrementAndGet();

    private final List<String> _whiteListedClassHierarchies;
    private final List<String> _blackListedClassHierarchies;

    /**
     * This is the "root" mutex that must be held when doing anything that could be impacted by failover. This must be
     * held by any child objects of this connection such as the session, producers and consumers.
     */
    private final Object _failoverMutex = new Object();

    private final Object _sessionCreationLock = new Object();

    /**
     * A channel is roughly analogous to a session. The server can negotiate the maximum number of channels per session
     * and we must prevent the client from opening too many.
     */
    private long _maximumChannelCount;

    /** The maximum size of frame supported by the server */
    private long _maximumFrameSize;

    /**
     * The protocol handler dispatches protocol events for this connection. For example, when the connection is dropped
     * the handler deals with this. It also deals with the initial dispatch of any protocol frames to their appropriate
     * handler.
     */
    private final AMQProtocolHandler _protocolHandler;

    /** Maps from session id (Integer) to AMQSession instance */
    private final ChannelToSessionMap _sessions = new ChannelToSessionMap();

    private String _clientName;

    /** The user name to use for authentication */
    private String _username;

    /** The password to use for authentication */
    private String _password;

    /** The virtual path to connect to on the AMQ server */
    private String _virtualHost;

    /** The exception listener for this connection object. */
    private volatile ExceptionListener _exceptionListener;

    private ConnectionListener _connectionListener;

    private final ConnectionURL _connectionURL;

    /**
     * Whether this connection is started, i.e. whether messages are flowing to consumers. It has no meaning for message
     * publication.
     */
    private volatile boolean _started;

    /** Policy dictating how to failover */
    private FailoverPolicy _failoverPolicy;

    /*
     * _Connected should be refactored with a suitable wait object.
     */
    private boolean _connected;

    private boolean _connectionAttempted;

    /*
     * The connection meta data
     */
    private QpidConnectionMetaData _connectionMetaData;

    private String _defaultTopicExchangeName = ExchangeDefaults.TOPIC_EXCHANGE_NAME;
    private String _defaultQueueExchangeName = ExchangeDefaults.DIRECT_EXCHANGE_NAME;
    private String _temporaryTopicExchangeName = ExchangeDefaults.TOPIC_EXCHANGE_NAME;
    private String _temporaryQueueExchangeName = ExchangeDefaults.DIRECT_EXCHANGE_NAME;

    /**
     * Thread Pool for executing connection level processes such as reporting asynchronous exceptions
     * and for 0-8..0-91 returning bounced messages.
     */
    private final ScheduledExecutorService _taskPool = Executors.newSingleThreadScheduledExecutor(new ThreadFactory()
    {
        @Override
        public Thread newThread(final Runnable r)
        {
            final String name = "Connection_" + AMQConnection.this._connectionNumber + "_task";
            _logger.debug("Creating connection pooled thread '{}'", name);
            Thread thread = new Thread(r, name);
            if (!thread.isDaemon())
            {
                thread.setDaemon(true);
            }

            return thread;
        }
    });

    private AMQConnectionDelegate _delegate;

    // this connection maximum number of prefetched messages
    private int _maxPrefetch;

    //Indicates whether persistent messages are synchronized
    private boolean _syncPersistence;

    //Indicates whether we need to sync on every message ack
    private boolean _syncAck;

    //Indicates whether we need to sync on every message ack on a client ack session, default to true
    private final boolean _syncClientAck;

    //Indicates the sync publish options (persistent|all)
    //By default it's async publish
    private String _syncPublish = "";

    //Indicates whether user-id should be attached to every sent message
    //By default the user ID is attached
    private boolean _populateUserId = true;

    // Indicates whether to use the old map message format or the
    // new amqp-0-10 encoded format.
    private boolean _useLegacyMapMessageFormat;

    // Indicates whether to use the old stream message format or the
    // new amqp-0-10 list encoded format.
    private boolean _useLegacyStreamMessageFormat;

    // When sending to a Queue destination for the first time, check that the queue is bound
    private final boolean _validateQueueOnSend;

    //used to track the last failover time for
    //Address resolution purposes
    private volatile long _lastFailoverTime = 0;

    private boolean _compressMessages;
    private int _messageCompressionThresholdSize;

    private final Map<String, String> _virtualHostProperties = new HashMap<>();
    private volatile boolean _virtualHostPropertiesPopulated;

    static
    {
        if (_logger.isDebugEnabled())
        {
            _logger.debug("Qpid version : " +  CommonProperties.getVersionString());
        }

        // The registering of any additional SASL mechanisms with the Java Security API requires
        // SecurityManager permissions.  In execution environments such as web containers,
        // this may require adjustments to the Java security.policy.
        CallbackHandlerRegistry registry = CallbackHandlerRegistry.getInstance();
        if (_logger.isDebugEnabled())
        {
           _logger.debug("Loaded mechanisms " + registry.getMechanisms());
        }
    }

    private ConnectionSettings _connectionSettings;
    private final ConcurrentMap<String, KeyStore> _brokerTrustStores = new ConcurrentHashMap<>();
    private Session _brokerTrustStoreSession;

    /**
     * @param broker      brokerdetails
     * @param username    username
     * @param password    password
     * @param clientName  clientid
     * @param virtualHost virtualhost
     *
     * @throws QpidException
     * @throws URLSyntaxException
     */
    public AMQConnection(String broker, String username, String password, String clientName, String virtualHost)
            throws QpidException, URLSyntaxException
    {
        this(new AMQConnectionURL(
                ConnectionURL.AMQ_PROTOCOL + "://" + username + ":" + password + "@"
                + ((clientName == null) ? "" : clientName) + "/" + virtualHost + "?brokerlist='"
                + BrokerDetails.checkTransport(broker) + "'"));
    }

    public AMQConnection(String host, int port, String username, String password, String clientName, String virtualHost)
            throws QpidException, URLSyntaxException
    {
        this(new AMQConnectionURL(
                   ConnectionURL.AMQ_PROTOCOL + "://" + username + ":" + password + "@"
                   + ((clientName == null) ? "" : clientName) + virtualHost + "?brokerlist='tcp://" + host + ":" + port + "'"));
    }

    public AMQConnection(String connection) throws QpidException, URLSyntaxException
    {
        this(new AMQConnectionURL(connection));
    }

    public AMQConnection(ConnectionURL connectionURL) throws QpidException
    {
        boolean success = false;
        try
        {
            if (connectionURL == null)
            {
                throw new IllegalArgumentException("Connection must be specified");
            }

            if (_logger.isDebugEnabled())
            {
                _logger.debug("Connection(" + _connectionNumber + "):" + connectionURL);
            }

            // set this connection maxPrefetch
            if (connectionURL.getOption(ConnectionURL.OPTIONS_MAXPREFETCH) != null)
            {
                _maxPrefetch = Integer.parseInt(connectionURL.getOption(ConnectionURL.OPTIONS_MAXPREFETCH));
            }
            else
            {
                // use the default value set for all connections
                _maxPrefetch = Integer.parseInt(System.getProperties().getProperty(ClientProperties.MAX_PREFETCH_PROP_NAME,
                        ClientProperties.MAX_PREFETCH_DEFAULT));
            }

            if (connectionURL.getOption(ConnectionURL.OPTIONS_SYNC_PERSISTENCE) != null)
            {
                _syncPersistence =
                    Boolean.parseBoolean(connectionURL.getOption(ConnectionURL.OPTIONS_SYNC_PERSISTENCE));
                _logger.warn("sync_persistence is a deprecated property, " +
                        "please use sync_publish={persistent|all} instead");
            }
            else
            {
                // use the default value set for all connections
                _syncPersistence = Boolean.getBoolean(ClientProperties.SYNC_PERSISTENT_PROP_NAME);
                if (_syncPersistence)
                {
                    _logger.warn("sync_persistence is a deprecated property, " +
                            "please use sync_publish={persistent|all} instead");
                }
            }

            if (connectionURL.getOption(ConnectionURL.OPTIONS_SYNC_ACK) != null)
            {
                _syncAck = Boolean.parseBoolean(connectionURL.getOption(ConnectionURL.OPTIONS_SYNC_ACK));
            }
            else
            {
                // use the default value set for all connections
                _syncAck = Boolean.getBoolean(ClientProperties.SYNC_ACK_PROP_NAME);
            }

            if (connectionURL.getOption(ConnectionURL.OPTIONS_SYNC_CLIENT_ACK) != null)
            {
                _syncClientAck = Boolean.parseBoolean(connectionURL.getOption(ConnectionURL.OPTIONS_SYNC_CLIENT_ACK));
            }
            else
            {
                String legacyProperty = System.getProperty("qpid.sync_after_client.ack");
                if (legacyProperty != null)
                {
                    _logger.warn("'qpid.sync_after_client.ack' is a deprecated system property, " +
                                 "please use '{}' instead", ClientProperties.SYNC_CLIENT_ACK);
                }
                _syncClientAck = Boolean.parseBoolean(System.getProperty(ClientProperties.SYNC_CLIENT_ACK,
                                                                         legacyProperty != null ? legacyProperty : "true"));
            }

            if (connectionURL.getOption(ConnectionURL.OPTIONS_SYNC_PUBLISH) != null)
            {
                _syncPublish = connectionURL.getOption(ConnectionURL.OPTIONS_SYNC_PUBLISH);
            }
            else
            {
                // use the default value set for all connections
                _syncPublish = System.getProperty((ClientProperties.SYNC_PUBLISH_PROP_NAME),_syncPublish);
            }

            if (connectionURL.getOption(ConnectionURL.OPTIONS_POPULATE_USER_ID) != null)
            {
                _populateUserId = Boolean.parseBoolean(connectionURL.getOption(ConnectionURL.OPTIONS_POPULATE_USER_ID));
            }

            if (connectionURL.getOption(ConnectionURL.OPTIONS_USE_LEGACY_MAP_MESSAGE_FORMAT) != null)
            {
                _useLegacyMapMessageFormat =  Boolean.parseBoolean(
                        connectionURL.getOption(ConnectionURL.OPTIONS_USE_LEGACY_MAP_MESSAGE_FORMAT));
            }
            else
            {
                // use the default value set for all connections
                _useLegacyMapMessageFormat = Boolean.getBoolean(ClientProperties.USE_LEGACY_MAP_MESSAGE_FORMAT);
            }

            if (connectionURL.getOption(ConnectionURL.OPTIONS_USE_LEGACY_STREAM_MESSAGE_FORMAT) != null)
            {
                _useLegacyStreamMessageFormat =  Boolean.parseBoolean(
                        connectionURL.getOption(ConnectionURL.OPTIONS_USE_LEGACY_STREAM_MESSAGE_FORMAT));
            }
            else
            {
                // use the default value set for all connections
                _useLegacyStreamMessageFormat = System.getProperty(ClientProperties.USE_LEGACY_STREAM_MESSAGE_FORMAT) == null ?
                        true : Boolean.getBoolean(ClientProperties.USE_LEGACY_STREAM_MESSAGE_FORMAT);
            }

            if(connectionURL.getOption(ConnectionURL.OPTIONS_VERIFY_QUEUE_ON_SEND) != null)
            {
                _validateQueueOnSend = Boolean.parseBoolean(
                                    connectionURL.getOption(ConnectionURL.OPTIONS_VERIFY_QUEUE_ON_SEND));
            }
            else
            {
                _validateQueueOnSend =
                    Boolean.parseBoolean(System.getProperty(ClientProperties.VERIFY_QUEUE_ON_SEND, "false"));
            }

            if(connectionURL.getOption(ConnectionURL.OPTIONS_COMPRESS_MESSAGES) != null)
            {
                _compressMessages = Boolean.parseBoolean(connectionURL.getOption(ConnectionURL.OPTIONS_COMPRESS_MESSAGES));
            }
            else
            {
                _compressMessages =
                        Boolean.parseBoolean(System.getProperty(ClientProperties.CONNECTION_OPTION_COMPRESS_MESSAGES,
                                             String.valueOf(ClientProperties.DEFAULT_CONNECTION_OPTION_COMPRESS_MESSAGES)));
            }

            if(connectionURL.getOption(ConnectionURL.OPTIONS_MESSAGES_COMPRESSION_THRESHOLD_SIZE) != null)
            {
                _messageCompressionThresholdSize = Integer.valueOf(connectionURL.getOption(ConnectionURL.OPTIONS_MESSAGES_COMPRESSION_THRESHOLD_SIZE));
            }
            else
            {
                _messageCompressionThresholdSize = Integer.getInteger(ClientProperties.CONNECTION_OPTION_MESSAGE_COMPRESSION_THRESHOLD_SIZE,
                                                                    ClientProperties.DEFAULT_MESSAGE_COMPRESSION_THRESHOLD_SIZE);
            }
            if(_messageCompressionThresholdSize <= 0)
            {
                _messageCompressionThresholdSize = Integer.MAX_VALUE;
            }

            String amqpVersion = System.getProperty((ClientProperties.AMQP_VERSION), "0-10");
            if (_logger.isDebugEnabled())
            {
                _logger.debug("AMQP version " + amqpVersion);
            }

            _failoverPolicy = new FailoverPolicy(connectionURL, this);
            if ("0-8".equals(amqpVersion))
            {
                _delegate = new AMQConnectionDelegate_8_0(this);
            }
            else if ("0-9".equals(amqpVersion))
            {
                _delegate = new AMQConnectionDelegate_0_9(this);
            }
            else if ("0-91".equals(amqpVersion) || "0-9-1".equals(amqpVersion))
            {
                _delegate = new AMQConnectionDelegate_0_91(this);
            }
            else
            {
                _delegate = new AMQConnectionDelegate_0_10(this);
            }

            _connectionURL = connectionURL;

            _clientName = connectionURL.getClientName();
            _username = connectionURL.getUsername();
            _password = connectionURL.getPassword();

            setVirtualHost(connectionURL.getVirtualHost());

            if (connectionURL.getDefaultQueueExchangeName() != null)
            {
                _defaultQueueExchangeName = connectionURL.getDefaultQueueExchangeName();
            }

            if (connectionURL.getDefaultTopicExchangeName() != null)
            {
                _defaultTopicExchangeName = connectionURL.getDefaultTopicExchangeName();
            }

            if (connectionURL.getTemporaryQueueExchangeName() != null)
            {
                _temporaryQueueExchangeName = connectionURL.getTemporaryQueueExchangeName();
            }

            if (connectionURL.getTemporaryTopicExchangeName() != null)
            {
                _temporaryTopicExchangeName = connectionURL.getTemporaryTopicExchangeName();
            }

            _protocolHandler = new AMQProtocolHandler(this);

            if (_logger.isDebugEnabled())
            {
                _logger.debug("Connecting with ProtocolHandler Version:"+_protocolHandler.getProtocolVersion());
            }

            // We are not currently connected
            setConnected(false);

            if (_clientName != null)
            {
                makeConnection();
            }

            _connectionMetaData = new QpidConnectionMetaData();

            if (connectionURL.getOption(ConnectionURL.OPTIONS_OBJECT_MESSAGE_CLASS_HIERARCHY_WHITE_LIST) != null)
            {
                String whiteListedClassHierarchiesString = connectionURL.getOption(ConnectionURL.OPTIONS_OBJECT_MESSAGE_CLASS_HIERARCHY_WHITE_LIST);
                _whiteListedClassHierarchies = Arrays.asList(whiteListedClassHierarchiesString.split(","));
            }
            else
            {
                final String defaultWhiteListedClassHierarchiesString = System.getProperty(CommonProperties.QPID_SECURITY_OBJECT_MESSAGE_CLASS_HIERARCHY_WHITE_LIST, "*");
                _whiteListedClassHierarchies = Arrays.asList(defaultWhiteListedClassHierarchiesString.split(","));
            }

            if (connectionURL.getOption(ConnectionURL.OPTIONS_OBJECT_MESSAGE_CLASS_HIERARCHY_BLACK_LIST) != null)
            {
                String blackListedClassHierarchiesString = connectionURL.getOption(ConnectionURL.OPTIONS_OBJECT_MESSAGE_CLASS_HIERARCHY_BLACK_LIST);
                _blackListedClassHierarchies = Arrays.asList(blackListedClassHierarchiesString.split(","));
            }
            else
            {
                final String defaultBlackListedClassHierarchiesString = System.getProperty(CommonProperties.QPID_SECURITY_OBJECT_MESSAGE_CLASS_HIERARCHY_BLACK_LIST, "");
                _blackListedClassHierarchies = Arrays.asList(defaultBlackListedClassHierarchiesString.split(","));
            }
            success = true;
        }
        finally
        {
            if (!success)
            {
                shutdownTaskPool();
            }
        }
    }

    private void makeConnection() throws QpidException
    {
        _connectionAttempted = true;
        if(_clientName == null)
        {

            try
            {
                InetAddress addr = InetAddress.getLocalHost();
                _clientName =  addr.getHostName() + System.currentTimeMillis();
            }
            catch (UnknownHostException e)
            {
                _clientName = "UnknownHost" + UUID.randomUUID();
            }
        }
        BrokerDetails brokerDetails = _failoverPolicy.getCurrentBrokerDetails();
        boolean retryAllowed = true;
        Exception connectionException = null;
        while (!isConnected() && retryAllowed && brokerDetails != null)
        {
            ProtocolVersion pe = null;
            try
            {
                pe = makeBrokerConnection(brokerDetails);
            }
            catch (Exception e)
            {
                if (_logger.isInfoEnabled())
                {
                    _logger.info("Unable to connect to broker at " +
                                 _failoverPolicy.getCurrentBrokerDetails(),
                                 e);
                }
                connectionException = e;
            }

            if (pe != null)
            {
                // reset the delegate to the version returned by the
                // broker
                initDelegate(pe);
            }
            else if (!isConnected())
            {
                if(connectionException instanceof ConnectionRedirectException)
                {
                    ConnectionRedirectException redirect = (ConnectionRedirectException) connectionException;
                    retryAllowed = true;
                    brokerDetails = new BrokerDetails(brokerDetails);
                    brokerDetails.setHost(redirect.getHost());
                    brokerDetails.setPort(redirect.getPort());
                    _protocolHandler.setStateManager(new AMQStateManager(_protocolHandler.getProtocolSession()));

                }
                else
                {
                    retryAllowed = _failoverPolicy.failoverAllowed();
                    brokerDetails = _failoverPolicy.getNextBrokerDetails();
                    _protocolHandler.setStateManager(new AMQStateManager(_protocolHandler.getProtocolSession()));
                }

            }
        }
        verifyClientID();

        if (_logger.isDebugEnabled())
        {
            _logger.debug("Are we connected:" + isConnected());
        }

        if (!isConnected())
        {
            if (_logger.isDebugEnabled())
            {
                _logger.debug("Last attempted ProtocolHandler Version:"+_protocolHandler.getProtocolVersion());
            }

            String message = null;

            if (connectionException != null)
            {
                if (connectionException.getCause() != null)
                {
                    message = connectionException.getCause().getMessage();
                }
                else
                {
                    message = connectionException.getMessage();
                }
            }

            if (message == null)
            {
                message = "Unable to Connect";
            }
            else if("".equals(message))
            {
                message = "Unable to Connect:" + connectionException.getClass();
            }

            for (Throwable th = connectionException; th != null; th = th.getCause())
            {
                if (th instanceof UnresolvedAddressException ||
                    th instanceof UnknownHostException)
                {
                    throw new AMQUnresolvedAddressException
                        (message,
                         _failoverPolicy.getCurrentBrokerDetails().toString(),
                         connectionException);
                }
            }

            throw new AMQConnectionFailureException(message, connectionException);
        }

        if (_logger.isDebugEnabled())
        {
        	_logger.debug("Connected with ProtocolHandler Version:"+_protocolHandler.getProtocolVersion());
        }

        _sessions.setMaxChannelID(_delegate.getMaxChannelID());
        _sessions.setMinChannelID(_delegate.getMinChannelID());
    }

    private void initDelegate(ProtocolVersion pe) throws AMQProtocolException
    {
        try
        {
            String delegateClassName = String.format
                                    ("org.apache.qpid.client.AMQConnectionDelegate_%s_%s",
                                     pe.getMajorVersion(), pe.getMinorVersion());
            if (_logger.isDebugEnabled())
            {
            	_logger.debug("Looking up delegate '" + delegateClassName + "' Based on PE:" + pe);
            }
            Class c = Class.forName(delegateClassName);
            Class partypes[] = new Class[1];
            partypes[0] = AMQConnection.class;
            _delegate = (AMQConnectionDelegate) c.getConstructor(partypes).newInstance(this);

            if (!ProtocolVersion.v0_10.equals(_delegate.getProtocolVersion()))
            {
                _protocolHandler.getProtocolSession().setProtocolVersion(_delegate.getProtocolVersion());
            }

            // reset state waiter state
            _protocolHandler.getStateManager().clearLastException();
            _protocolHandler.getStateManager().changeState(AMQState.CONNECTION_NOT_STARTED);
        }
        catch (ClassNotFoundException e)
        {
            String errorMessage = String.format("Protocol: %s.%s is required by the broker but is not " +
                                                "currently supported by this client library implementation",
                                                pe.getMajorVersion(), pe.getMinorVersion());

            throw new AMQProtocolException(errorMessage, e);
        }
        catch (NoSuchMethodException e)
        {
            throw new RuntimeException("unable to locate constructor for delegate", e);
        }
        catch (InstantiationException e)
        {
            throw new RuntimeException("error instantiating delegate", e);
        }
        catch (IllegalAccessException e)
        {
            throw new RuntimeException("error accessing delegate", e);
        }
        catch (InvocationTargetException e)
        {
            throw new RuntimeException("error invoking delegate", e);
        }
    }

    private void setVirtualHost(String virtualHost)
    {
        if (virtualHost != null && virtualHost.startsWith("/"))
        {
            virtualHost = virtualHost.substring(1);
        }

        _virtualHost = virtualHost;
    }

    public boolean attemptReconnection(String host, int port, final boolean useFailoverConfigOnFailure)
    {
        BrokerDetails bd = new BrokerDetails(_failoverPolicy.getCurrentBrokerDetails());
        bd.setHost(host);
        bd.setPort(port);

        _failoverPolicy.setBroker(bd);

        try
        {
            makeBrokerConnection(bd);

            return true;
        }
        catch (Exception e)
        {
            if (_logger.isInfoEnabled())
            {
                _logger.info("Unable to connect to broker at " + bd);
            }

            return useFailoverConfigOnFailure && attemptReconnection();
        }

    }

    public boolean attemptReconnection()
    {
        BrokerDetails broker;
        while (!isClosed() && !isClosing() && _failoverPolicy.failoverAllowed() && (broker = _failoverPolicy.getNextBrokerDetails()) != null)
        {
            if (attemptConnection(broker))
            {
                return true;
            }
        }

        // connection unsuccessful
        return false;
    }

    private boolean attemptConnection(final BrokerDetails broker)
    {
        try
        {
            makeBrokerConnection(broker);
            return true;
        }
        catch (Exception e)
        {
            if (!(e instanceof QpidException))
            {
                if (_logger.isInfoEnabled())
                {
                    _logger.info("Unable to connect to broker at " + _failoverPolicy.getCurrentBrokerDetails(), e);
                }
            }
            else
            {
                if (_logger.isInfoEnabled())
                {
                    _logger.info(e.getMessage() + ":Unable to connect to broker at "
                                 + _failoverPolicy.getCurrentBrokerDetails());
                }
            }
        }
        return false;
    }

    public ProtocolVersion makeBrokerConnection(BrokerDetails brokerDetail) throws IOException, QpidException
    {
        return _delegate.makeBrokerConnection(brokerDetail);
    }

    public <T, E extends Exception> T executeRetrySupport(FailoverProtectedOperation<T,E> operation) throws E
    {
        return _delegate.executeRetrySupport(operation);
    }

    /**
     * Get the details of the currently active broker
     *
     * @return null if no broker is active (i.e. no successful connection has been made, or the BrokerDetail instance
     *         otherwise
     */
    public BrokerDetails getActiveBrokerDetails()
    {
        return _failoverPolicy.getCurrentBrokerDetails();
    }

    public boolean failoverAllowed()
    {
        if (!isConnected())
        {
            return false;
        }
        else
        {
            return _failoverPolicy.failoverAllowed();
        }
    }

    public org.apache.qpid.jms.Session createSession(final boolean transacted, final int acknowledgeMode) throws JMSException
    {
        return createSession(transacted, acknowledgeMode, _maxPrefetch);
    }

    public org.apache.qpid.jms.Session createSession(final boolean transacted, final int acknowledgeMode, final int prefetch)
            throws JMSException
    {
        return createSession(transacted, acknowledgeMode, prefetch, prefetch);
    }

    public org.apache.qpid.jms.Session createSession(final boolean transacted, final int acknowledgeMode,
                                                     final int prefetchHigh, final int prefetchLow) throws JMSException
    {
        synchronized (_sessionCreationLock)
        {

            checkNotClosed();

            if(!_connectionAttempted)
            {
                try
                {
                    makeConnection();
                }
                catch (QpidException e)
                {
                    throw JMSExceptionHelper.chainJMSException(new JMSException("Unable to establish connection"),e);
                }
            }

            if(_delegate.isVirtualHostPropertiesSupported() && !_virtualHostPropertiesPopulated)
            {
                retrieveVirtualHostPropertiesIfNecessary();
            }
            return _delegate.createSession(transacted, acknowledgeMode, prefetchHigh, prefetchLow);
        }
    }

    private void retrieveVirtualHostPropertiesIfNecessary() throws JMSException
    {
        synchronized (_virtualHostProperties)
        {
            if(!_virtualHostPropertiesPopulated)
            {
                final Session session = _delegate.createSession(false, AMQSession.NO_ACKNOWLEDGE, 3,3);
                final MessageConsumer consumer = session.createConsumer(session.createQueue(
                        "ADDR: $virtualhostProperties; {assert: never, create: never, node:{ type: queue }}"));
                try
                {
                    ((AMQSession)session).start();
                }
                catch (QpidException e)
                {
                    throw JMSExceptionHelper.chainJMSException(new JMSException(
                            "Failed to retrieve virtual host properties"), e);
                }
                Message propertiesMessage = consumer.receive(getProtocolHandler().getDefaultTimeout());
                if(propertiesMessage != null)
                {
                    for(String property : Collections.list((Enumeration<String>) propertiesMessage.getPropertyNames()))
                    {
                        _virtualHostProperties.put(property, propertiesMessage.getStringProperty(property));
                    }
                }
                session.close();
                _virtualHostPropertiesPopulated = true;
            }
        }
    }

    public KeyStore getBrokerSuppliedTrustStore(final String name) throws JMSException
    {
        synchronized(_brokerTrustStores)
        {
            if(!_brokerTrustStores.containsKey(name))
            {
                if(_brokerTrustStoreSession == null)
                {
                    _brokerTrustStoreSession = _delegate.createSession(false, AMQSession.AUTO_ACKNOWLEDGE, 1, 1);
                    try
                    {
                        ((AMQSession) _brokerTrustStoreSession).start();
                    }
                    catch (QpidException e)
                    {
                        throw JMSExceptionHelper.chainJMSException(new JMSException(
                                "Failed to retrieve virtual host properties"), e);
                    }
                }
                final MessageConsumer consumer = _brokerTrustStoreSession.createConsumer(_brokerTrustStoreSession.createQueue(
                        "ADDR: " + name + "; {assert: never, create: never, node:{ type: queue }}"));
                final Message message  = consumer.receive(2000l);
                if(message != null)
                {
                    StreamMessage streamMessage = (StreamMessage) message;
                    List<X509Certificate> certs = new ArrayList<>();
                    try
                    {
                        try
                        {

                            final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
                            byte[] bytes;
                            while ((bytes = (byte[]) streamMessage.readObject()) != null)
                            {
                                certs.add((X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(
                                        bytes)));
                            }
                        }
                        catch (MessageEOFException e)
                        {
                            // end of message
                        }
                        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());

                        char[] encryptionTrustStorePassword =
                                getConnectionSettings().getEncryptionTrustStorePassword() == null
                                        ? null
                                        : getConnectionSettings().getEncryptionTrustStorePassword().toCharArray();

                        keyStore.load(null, encryptionTrustStorePassword);
                        int i = 1;
                        for (X509Certificate cert : certs)
                        {
                            keyStore.setCertificateEntry(String.valueOf(i++), cert);
                        }
                        _brokerTrustStores.put(name, keyStore);
                    }
                    catch (JMSException | GeneralSecurityException | IOException e)
                    {
                        _logger.error(e.getMessage(), e);
                    }
                }

            }
            return _brokerTrustStores.get(name);

        }
    }

    public void setFailoverPolicy(FailoverPolicy policy)
    {
        _failoverPolicy = policy;
    }

    public FailoverPolicy getFailoverPolicy()
    {
        return _failoverPolicy;
    }

    /**
     * Returns an AMQQueueSessionAdaptor which wraps an AMQSession and throws IllegalStateExceptions where specified in
     * the JMS spec
     *
     * @param transacted
     * @param acknowledgeMode
     *
     * @return QueueSession
     *
     * @throws JMSException
     */
    public QueueSession createQueueSession(boolean transacted, int acknowledgeMode) throws JMSException
    {
        return new AMQQueueSessionAdaptor(createSession(transacted, acknowledgeMode));
    }

    /**
     * Returns an AMQTopicSessionAdapter which wraps an AMQSession and throws IllegalStateExceptions where specified in
     * the JMS spec
     *
     * @param transacted
     * @param acknowledgeMode
     *
     * @return TopicSession
     *
     * @throws JMSException
     */
    public TopicSession createTopicSession(boolean transacted, int acknowledgeMode) throws JMSException
    {
        return new AMQTopicSessionAdaptor(createSession(transacted, acknowledgeMode));
    }

    public boolean channelLimitReached()
    {
        return _sessions.size() >= _maximumChannelCount;
    }

    public String getClientID() throws JMSException
    {
        checkNotClosed();

        return _clientName;
    }

    public void setClientID(String clientID) throws JMSException
    {
        checkNotClosed();
        synchronized(_sessionCreationLock)
        {
            if(_connectionAttempted)
            {
                // in AMQP it is not possible to change the client ID. If one is not specified
                // upon connection construction, an id is generated automatically. Therefore
                // we can always throw an exception.
                if (!Boolean.getBoolean(ClientProperties.IGNORE_SET_CLIENTID_PROP_NAME))
                {
                    throw new IllegalStateException("Client name cannot be changed after being set");
                }
                else
                {
                    _logger.info("Operation setClientID is ignored using ID: " + getClientID());
                }
            }
            else
            {
                _clientName = clientID;
            }
        }
    }

    public ConnectionMetaData getMetaData() throws JMSException
    {
        checkNotClosed();

        return _connectionMetaData;

    }

    protected final ExceptionListener getExceptionListenerNoCheck()
    {
        return _exceptionListener;
    }

    public ExceptionListener getExceptionListener() throws JMSException
    {
        checkNotClosed();
        return getExceptionListenerNoCheck();
    }

    public void setExceptionListener(ExceptionListener listener) throws JMSException
    {
        checkNotClosed();

        _exceptionListener = listener;
    }

    /**
     * Start the connection, i.e. start flowing messages. Note that this method must be called only from a single thread
     * and is not thread safe (which is legal according to the JMS specification).
     *
     * @throws JMSException
     */
    public void start() throws JMSException
    {
        checkNotClosed();
        if (!_started)
        {
            _started = true;
            final Iterator it = _sessions.values().iterator();
            while (it.hasNext())
            {
                final AMQSession s = (AMQSession) (it.next());
                try
                {
                    s.start();
                }
                catch (QpidException e)
                {
                    throw JMSExceptionHelper.chainJMSException(new JMSException("Connection.start failed"), e);
                }
            }

        }
    }

    public void stop() throws JMSException
    {
        checkNotClosed();
        if (_started)
        {
            for (Iterator i = _sessions.values().iterator(); i.hasNext();)
            {
                try
                {
                    ((AMQSession) i.next()).stop();
                }
                catch (QpidException e)
                {
                    throw JMSExceptionHelper.chainJMSException(new JMSException("Connection.stop failed."), e);
                }
            }

            _started = false;
        }
    }

    public void close() throws JMSException
    {
        close(DEFAULT_CLOSE_TIMEOUT);
    }

    private void close(long timeout) throws JMSException
    {
        boolean closed;

        synchronized (_sessionCreationLock)
        {
            closed = setClosed();
        }

        try
        {
            if (!closed)
            {
                List<AMQSession> sessions = new ArrayList<>(_sessions.values());

                setClosing(true);
                try
                {
                    doClose(sessions, timeout);
                }
                finally
                {
                    setClosing(false);
                }
            }
        }
        finally
        {
            shutdownTaskPool();
        }
    }

    private void doClose(List<AMQSession> sessions, long timeout) throws JMSException
    {
        if (!sessions.isEmpty())
        {
            AMQSession session = sessions.remove(0);
            session.lockMessageDelivery();
            try
            {
                doClose(sessions, timeout);
            }
            finally
            {
                session.unlockMessageDelivery();
            }
        }
        else
        {
            synchronized (getFailoverMutex())
            {
                try
                {
                    closeAllSessions(null, timeout);
                }
                catch (JMSException e)
                {
                    _logger.warn("Error closing connection", e);
                    throw JMSExceptionHelper.chainJMSException(new JMSException("Error closing connection: " + e), e);
                }
                finally
                {
                    try
                    {
                        _delegate.closeConnection(timeout);
                    }
                    catch (Exception e)
                    {
                        _logger.warn("Error closing underlying protocol connection", e);
                    }
                }
            }
        }
    }

    private void shutdownTaskPool()
    {
        _taskPool.shutdown();
    }

    /**
     * Marks all sessions and their children as closed without sending any protocol messages. Useful when you need to
     * mark objects "visible" in userland as closed after failover or other significant event that impacts the
     * connection. <p/> The caller must hold the failover mutex before calling this method.
     */
    private void markAllSessionsClosed()
    {
        final LinkedList sessionCopy = new LinkedList(_sessions.values());
        final Iterator it = sessionCopy.iterator();
        while (it.hasNext())
        {
            final AMQSession session = (AMQSession) it.next();

            session.markClosed();
        }

        _sessions.clear();
    }

    /**
     * Close all the sessions, either due to normal connection closure or due to an error occurring.
     *
     * @param cause if not null, the error that is causing this shutdown <p/> The caller must hold the failover mutex
     *              before calling this method.
     */
    private void closeAllSessions(Throwable cause, long timeout) throws JMSException
    {
        final LinkedList sessionCopy = new LinkedList(_sessions.values());
        final Iterator it = sessionCopy.iterator();
        JMSException sessionException = null;
        while (it.hasNext())
        {
            final AMQSession session = (AMQSession) it.next();
            if (cause != null)
            {
                session.closed(cause);
            }
            else
            {
                try
                {
                    session.close(timeout);
                }
                catch (JMSException e)
                {
                    _logger.warn("Error closing session: " + e);
                    sessionException = e;
                }
            }
        }

        _sessions.clear();
        if (sessionException != null)
        {
            throw sessionException;
        }
    }

    public ConnectionConsumer createConnectionConsumer(Destination destination, String messageSelector,
                                                       ServerSessionPool sessionPool, int maxMessages) throws JMSException
    {
        checkNotClosed();

        throw new JmsNotImplementedException();

    }

    public ConnectionConsumer createConnectionConsumer(Queue queue, String messageSelector, ServerSessionPool sessionPool,
                                                       int maxMessages) throws JMSException
    {
        checkNotClosed();

        throw new JmsNotImplementedException();
    }

    public ConnectionConsumer createConnectionConsumer(Topic topic, String messageSelector, ServerSessionPool sessionPool,
                                                       int maxMessages) throws JMSException
    {
        checkNotClosed();

        throw new JmsNotImplementedException();
    }

    public ConnectionConsumer createDurableConnectionConsumer(Topic topic, String subscriptionName, String messageSelector,
                                                              ServerSessionPool sessionPool, int maxMessages) throws JMSException
    {
        checkNotClosed();

        throw new JmsNotImplementedException();
    }

    public long getMaximumChannelCount() throws JMSException
    {
        checkNotClosed();

        return _maximumChannelCount;
    }

    public void setConnectionListener(ConnectionListener listener)
    {
        _connectionListener = listener;
    }

    public ConnectionListener getConnectionListener()
    {
        return _connectionListener;
    }

    public void setMaximumChannelCount(long maximumChannelCount)
    {
        _maximumChannelCount = maximumChannelCount;
    }

    public void setMaximumFrameSize(long frameMax)
    {
        _maximumFrameSize = frameMax;
    }

    public long getMaximumFrameSize()
    {
        return _maximumFrameSize;
    }

    public ChannelToSessionMap getSessions()
    {
        return _sessions;
    }

    public String getUsername()
    {
        return _username;
    }

    public void setUsername(String id)
    {
        _username = id;
    }

    public String getPassword()
    {
        return _password;
    }

    public String getVirtualHost()
    {
        return _virtualHost;
    }

    public final AMQProtocolHandler getProtocolHandler()
    {
        return _protocolHandler;
    }

    public final boolean started()
    {
        return _started;
    }

    public final boolean isConnected()
    {
        return _connected;
    }

    protected final void setConnected(boolean connected)
    {
        _connected = connected;
    }

    public void bytesSent(long writtenBytes)
    {
        if (_connectionListener != null)
        {
            _connectionListener.bytesSent(writtenBytes);
        }
    }

    public void bytesReceived(long receivedBytes)
    {
        if (_connectionListener != null)
        {
            _connectionListener.bytesReceived(receivedBytes);
        }
    }

    /**
     * Fire the preFailover event to the registered connection listener (if any)
     *
     * @param redirect true if this is the result of a redirect request rather than a connection error
     *
     * @return true if no listener or listener does not veto change
     */
    public boolean firePreFailover(boolean redirect)
    {
        _lastFailoverTime = System.currentTimeMillis();
        boolean proceed = true;
        if (_connectionListener != null)
        {
            proceed = _connectionListener.preFailover(redirect);
        }

        return proceed;
    }

    /**
     * Fire the preResubscribe event to the registered connection listener (if any). If the listener vetoes
     * resubscription then all the sessions are closed.
     *
     * @return true if no listener or listener does not veto resubscription.
     *
     * @throws JMSException
     */
    public boolean firePreResubscribe() throws JMSException
    {
        if (_connectionListener != null)
        {
            boolean resubscribe = _connectionListener.preResubscribe();
            if (!resubscribe)
            {
                markAllSessionsClosed();
            }

            return resubscribe;
        }
        else
        {
            return true;
        }
    }

    /** Fires a failover complete event to the registered connection listener (if any). */
    public void fireFailoverComplete()
    {
        if (_connectionListener != null)
        {
            _connectionListener.failoverComplete();
        }
    }

    /**
     * In order to protect the consistency of the connection and its child sessions, consumers and producers, the
     * "failover mutex" must be held when doing any operations that could be corrupted during failover.
     *
     * @return a mutex. Guaranteed never to change for the lifetime of this connection even if failover occurs.
     */
    public final Object getFailoverMutex()
    {
        return _failoverMutex;
    }

    public void resubscribeSessions() throws JMSException, QpidException, FailoverException
    {
        _delegate.resubscribeSessions();
    }

    /**
     * If failover is taking place this will block until it has completed. If failover is not taking place it will
     * return immediately.
     *
     * @throws InterruptedException
     */
    public void blockUntilNotFailingOver() throws InterruptedException
    {
        _protocolHandler.blockUntilNotFailingOver();
    }

    /**
     * Invoked by the AMQProtocolSession when a protocol session exception has occurred. This method sends the exception
     * to a JMS exception listener, if configured, and propagates the exception to sessions, which in turn will
     * propagate to consumers. This allows synchronous consumers to have exceptions thrown to them.
     *
     * @param cause the exception
     */
    public void exceptionReceived(Throwable cause)
    {

        if (_logger.isDebugEnabled())
        {
            _logger.debug("exceptionReceived done by:" + Thread.currentThread().getName(), cause);
        }

        final JMSException je = convertToJMSException(cause);

        try
        {
            if (hardError(cause))
            {
                closeSessions(cause);
            }
        }
        finally
        {
            deliverJMSExceptionToExceptionListenerOrLog(je, cause);
        }
    }

    private JMSException convertToJMSException(Throwable cause)
    {
        final JMSException je;
        if (cause instanceof JMSException)
        {
            je = (JMSException) cause;
        }
        else
        {
            int errorCode = 0;

            if (cause instanceof AMQException)
            {
                errorCode = ((AMQException) cause).getErrorCode();
            }

            if (errorCode != 0)
            {
                je = JMSExceptionHelper.chainJMSException(new JMSException("Exception thrown against "
                                                                           + toString()
                                                                           + ": "
                                                                           + cause, Integer.toString(errorCode)),
                                                          cause);
            }
            else
            {
                //Should never get here as all AMQEs are required to have an ErrorCode!
                // Other than AMQDisconnectedEx!

                if (cause instanceof AMQDisconnectedException)
                {
                    Exception last = _protocolHandler.getStateManager().getLastException();
                    if (last != null)
                    {
                        _logger.info("StateManager had an exception for us to use a cause of our Disconnected Exception");
                        cause = last;
                    }
                }
                je = JMSExceptionHelper.chainJMSException(new JMSException("Exception thrown against "
                                                                           + toString()
                                                                           + ": "
                                                                           + cause), cause);
            }
        }
        return je;
    }

    void closed(Throwable cause)
    {
        _logger.debug("Closing closed connection {} ", this.toString());

        final JMSException je = convertToJMSException(cause);
        try
        {
            _protocolHandler.getProtocolSession().notifyError(je);
            boolean performClose = !setClosed();

            // if we are closing the connection, close sessions first
            if (performClose)
            {
                closeSessions(cause);
            }
        }
        finally
        {
            deliverJMSExceptionToExceptionListenerOrLog(je, cause);
        }
    }

    private void closeSessions(Throwable cause)
    {
        // get the failover mutex before trying to close
        synchronized (getFailoverMutex())
        {
            try
            {
                closeAllSessions(cause, -1);
            }
            catch (JMSException e)
            {
                _logger.error("Error closing all sessions: " + e, e);
            }
        }
    }

    private void deliverJMSExceptionToExceptionListenerOrLog(final JMSException je, final Throwable cause)
    {
        final ExceptionListener exceptionListener = getExceptionListenerNoCheck();
        if (exceptionListener != null)
        {
            performConnectionTask(new Runnable()
                                  {
                                      @Override
                                      public void run()
                                      {
                                          // deliver the exception if there is a listener
                                          try
                                          {
                                              exceptionListener.onException(je);
                                          }
                                          catch (RuntimeException e)
                                          {
                                              _logger.error("Exception occurred in ExceptionListener", e);
                                          }
                                      }
                                  });
        }
        else
        {
            _logger.error("Throwable Received but no listener set: " + cause);
        }


    }

    private boolean hardError(Throwable cause)
    {
        if (cause instanceof AMQException)
        {
            return ((AMQException) cause).isHardError();
        }

        return true;
    }

    void registerSession(int channelId, AMQSession session)
    {
        _sessions.put(channelId, session);
    }

    public void deregisterSession(int channelId)
    {
        _sessions.remove(channelId);
    }

    public String toString()
    {
        StringBuffer buf = new StringBuffer("AMQConnection:\n");
        if (_failoverPolicy.getCurrentBrokerDetails() == null)
        {
            buf.append("No active broker connection");
        }
        else
        {
            BrokerDetails bd = _failoverPolicy.getCurrentBrokerDetails();
            buf.append("Host: ").append(String.valueOf(bd.getHost()));
            buf.append("\nPort: ").append(String.valueOf(bd.getPort()));
        }

        buf.append("\nVirtual Host: ").append(String.valueOf(_virtualHost));
        buf.append("\nClient ID: ").append(String.valueOf(_clientName));
        buf.append("\nActive session count: ").append((_sessions == null) ? 0 : _sessions.size());

        return buf.toString();
    }

    /**
     * Returns connection url.
     * @return connection url
     */
    public ConnectionURL getConnectionURL()
    {
        return _connectionURL;
    }

    /**
     * Returns stringified connection url.   This url is suitable only for display
     * as {@link AMQConnectionURL#toString()} converts any password to asterisks.
     * @return connection url
     */
    public String toURL()
    {
        return _connectionURL.toString();
    }

    public Reference getReference() throws NamingException
    {
        return new Reference(AMQConnection.class.getName(), new StringRefAddr(JNDI_ADDRESS_CONNECTION_URL, toURL()),
                             ObjectFactory.class.getName(), null); // factory location
    }

    public String getDefaultTopicExchangeName()
    {
        return _defaultTopicExchangeName;
    }

    public void setDefaultTopicExchangeName(String defaultTopicExchangeName)
    {
        _defaultTopicExchangeName = defaultTopicExchangeName;
    }

    public String getDefaultQueueExchangeName()
    {
        return _defaultQueueExchangeName;
    }

    public void setDefaultQueueExchangeName(String defaultQueueExchangeName)
    {
        _defaultQueueExchangeName = defaultQueueExchangeName;
    }

    public String getTemporaryTopicExchangeName()
    {
        return _temporaryTopicExchangeName;
    }

    public String getTemporaryQueueExchangeName()
    {
        return _temporaryQueueExchangeName;
    }

    public void setTemporaryTopicExchangeName(String temporaryTopicExchangeName)
    {
        _temporaryTopicExchangeName = temporaryTopicExchangeName;
    }

    public void setTemporaryQueueExchangeName(String temporaryQueueExchangeName)
    {
        _temporaryQueueExchangeName = temporaryQueueExchangeName;
    }

    public void performConnectionTask(Runnable task)
    {
        try
        {
            _taskPool.execute(task);
        }
        catch (RejectedExecutionException e)
        {
            if(!(isClosed() || isClosing()))
            {
                throw e;
            }
        }
    }

    ScheduledFuture<?> scheduleTask(Runnable task, long initialDelay, long period, TimeUnit timeUnit)
    {
        return _taskPool.scheduleAtFixedRate(task, initialDelay, period, timeUnit);
    }

    public AMQSession getSession(int channelId)
    {
        return _sessions.get(channelId);
    }

    public ProtocolVersion getProtocolVersion()
    {
        return _delegate.getProtocolVersion();
    }

    public String getBrokerUUID()
    {
        if(getProtocolVersion().equals(ProtocolVersion.v0_10))
        {
            return ((AMQConnectionDelegate_0_10)_delegate).getUUID();
        }
        else
        {
            return null;
        }
    }

    /**
     * Tests whether the Broker has advertised support for the named feature.
     *
     * @param featureName
     *
     * @return true if the feature is supported, or false otherwise.
     */
    boolean isSupportedServerFeature(final String featureName)
    {
        return _delegate.isSupportedServerFeature(featureName);
    }

    public boolean isFailingOver()
    {
        return (_protocolHandler.getFailoverLatch() != null);
    }

    /**
     * Get the maximum number of messages that this connection can pre-fetch.
     *
     * @return The maximum number of messages that this connection can pre-fetch.
     */
    public long getMaxPrefetch()
    {
        return _maxPrefetch;
    }

    /**
     * Indicates whether persistent messages are synchronized
     *
     * @return true if persistent messages are synchronized false otherwise
     */
    public boolean getSyncPersistence()
    {
        return _syncPersistence;
    }

    /**
     * Indicates whether we need to sync on every message ack
     */
    public boolean getSyncAck()
    {
        return _syncAck;
    }

    boolean getSyncClientAck()
    {
        return _syncClientAck;
    }

    public String getSyncPublish()
    {
        return _syncPublish;
    }

    public boolean isPopulateUserId()
    {
        return _populateUserId;
    }

    public boolean isMessageCompressionDesired()
    {
        return _compressMessages;
    }

    public int getNextChannelID()
    {
        return _sessions.getNextChannelId();
    }

    public boolean isUseLegacyMapMessageFormat()
    {
        return _useLegacyMapMessageFormat;
    }

    public boolean isUseLegacyStreamMessageFormat()
    {
        return _useLegacyStreamMessageFormat;
    }

    private void verifyClientID() throws QpidException
    {
        if (Boolean.getBoolean(ClientProperties.QPID_VERIFY_CLIENT_ID))
        {
            try
            {
                if (!_delegate.verifyClientID())
                {
                    throw new AMQException(ErrorCodes.ALREADY_EXISTS, "ClientID must be unique");
                }
            }
            catch(JMSException e)
            {
                    throw new QpidException(e.getMessage(),e);
            }
        }
    }

    public long getLastFailoverTime()
    {
         return _lastFailoverTime;
    }

    protected AMQConnectionDelegate getDelegate()
    {
        return _delegate;
    }

    public Long getConnectionNumber()
    {
        return _connectionNumber;
    }

    protected void logConnected(SocketAddress localAddress, SocketAddress remoteAddress)
    {
        if(_logger.isInfoEnabled())
        {
            _logger.info("Connection " + _connectionNumber + " now connected from "
                         + localAddress + " to " + remoteAddress);
        }
    }

    void setHeartbeatListener(HeartbeatListener listener)
    {
        _delegate.setHeartbeatListener(listener);
    }

    public boolean validateQueueOnSend()
    {
        return _validateQueueOnSend;
    }

    public int getMessageCompressionThresholdSize()
    {
        return _messageCompressionThresholdSize;
    }

    void doWithAllLocks(Runnable r)
    {
        doWithAllLocks(r, _sessions.values());

    }

    private void doWithAllLocks(final Runnable r, final List<AMQSession> sessions)
    {
        if (!sessions.isEmpty())
        {
            AMQSession session = sessions.remove(0);


            Object dispatcherLock = session.getDispatcherLock();
            if (dispatcherLock == null)
            {
                dispatcherLock = new Object(); // use dummy intrinsic lock to make subsequent code nicer
            }
            synchronized (dispatcherLock)
            {
                session.lockMessageDelivery();
                try
                {
                    doWithAllLocks(r, sessions);
                }
                finally
                {
                    session.unlockMessageDelivery();
                }
            }
        }
        else
        {
            synchronized (getFailoverMutex())
            {
                r.run();
            }
        }
    }


    public String getTemporaryQueuePrefix()
    {
        if(_delegate.isVirtualHostPropertiesSupported())
        {
            final String prefix = getVirtualHostProperty("virtualHost.temporaryQueuePrefix");
            return prefix == null ? "" : prefix;
        }
        else
        {
            return "";
        }

    }

    String getVirtualHostProperty(final String propertyName)
    {
        return _virtualHostProperties.get(propertyName);
    }

    public void setConnectionSettings(final ConnectionSettings connectionSettings)
    {
        _connectionSettings = connectionSettings;
    }

    public ConnectionSettings getConnectionSettings()
    {
        return _connectionSettings;
    }

    @Override
    public boolean isTrusted(Class<?> clazz)
    {
        while (clazz.isArray())
        {
            clazz = clazz.getComponentType();
        }

        if (clazz.isPrimitive())
        {
            return true;
        }

        while (clazz != null && (clazz.isAnonymousClass() || clazz.isLocalClass()))
        {
            clazz = clazz.getEnclosingClass();
        }

        if (clazz == null || clazz.getCanonicalName() == null)
        {
            return false;
        }

        String className = clazz.getCanonicalName();

        for (String blackListedClassHierarchy : _blackListedClassHierarchies)
        {
            if ("*".equals(blackListedClassHierarchy))
            {
                return false;
            }
            else if (className != null && (className.equals(blackListedClassHierarchy) || className.startsWith(blackListedClassHierarchy + ".")))
            {
                return false;
            }
        }

        for (String whiteListedClassHierarchy : _whiteListedClassHierarchies)
        {
            if ("*".equals(whiteListedClassHierarchy))
            {
                return true;
            }
            else if (className != null && (className.equals(whiteListedClassHierarchy) || className.startsWith(whiteListedClassHierarchy + ".")))
            {
                return true;
            }
        }
        return false;
    }

    boolean isVirtualHostPropertiesSupported()
    {
        return getDelegate().isVirtualHostPropertiesSupported();
    }
}
