Merge from trunk

git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/QPID-6125-ProtocolRefactoring@1630749 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java b/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java
index 45e0c39..76e4415 100644
--- a/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java
+++ b/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java
@@ -27,6 +27,7 @@
 import org.apache.qpid.server.jmx.ManagedObject;
 import org.apache.qpid.server.jmx.ManagedObjectRegistry;
 import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.State;
 import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacade;
 import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHAVirtualHostNode;
 
@@ -46,7 +47,7 @@
     @Override
     public boolean isChildManageableByMBean(ConfiguredObject child)
     {
-        return child instanceof BDBHAVirtualHostNode;
+        return child instanceof BDBHAVirtualHostNode && ((BDBHAVirtualHostNode)child).getState() != State.ERRORED;
     }
 
     @Override
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBSystemConfigImpl.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBSystemConfigImpl.java
index 0fc4460..5d65d6e 100644
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBSystemConfigImpl.java
+++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBSystemConfigImpl.java
@@ -26,6 +26,7 @@
 import org.apache.qpid.server.logging.LogRecorder;
 import org.apache.qpid.server.model.AbstractSystemConfig;
 import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerShutdownProvider;
 import org.apache.qpid.server.model.ManagedAttributeField;
 import org.apache.qpid.server.model.ManagedObject;
 import org.apache.qpid.server.model.SystemConfigFactoryConstructor;
@@ -48,9 +49,10 @@
     public BDBSystemConfigImpl(final TaskExecutor taskExecutor,
                                final EventLogger eventLogger,
                                final LogRecorder logRecorder,
-                               final BrokerOptions brokerOptions)
+                               final BrokerOptions brokerOptions,
+                               final BrokerShutdownProvider brokerShutdownProvider)
     {
-        super(taskExecutor, eventLogger, logRecorder, brokerOptions);
+        super(taskExecutor, eventLogger, logRecorder, brokerOptions, brokerShutdownProvider);
     }
 
     @Override
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java
index 20dbdc7..532cffd 100644
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java
+++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java
@@ -1253,7 +1253,7 @@
     {
         if (LOGGER.isDebugEnabled())
         {
-            LOGGER.debug("Setting permitted nodes to " + permittedNodes);
+            LOGGER.debug(_prettyGroupNodeName + " permitted nodes set to " + permittedNodes);
         }
 
         _permittedNodes.clear();
@@ -1263,12 +1263,18 @@
             registerAppStateMonitorIfPermittedNodesSpecified();
 
             ReplicationGroupListener listener = _replicationGroupListener.get();
+            int count = 0;
             for(ReplicationNode node: _remoteReplicationNodes.values())
             {
                 if (!isNodePermitted(node))
                 {
                     onIntruder(listener, node);
                 }
+                count++;
+            }
+            if (LOGGER.isDebugEnabled())
+            {
+                LOGGER.debug(_prettyGroupNodeName + " checked  " + count + " node(s)");
             }
         }
     }
@@ -1329,7 +1335,7 @@
         }
         catch (IOException e)
         {
-            throw new IllegalConfigurationException(String.format("Cannot connect to '%s'", helperHostPort), e);
+            throw new IllegalConfigurationException(String.format("Cannot connect to existing node '%s' at '%s'", helperNodeName, helperHostPort), e);
         }
         catch (ServiceConnectFailedException e)
         {
@@ -1337,8 +1343,8 @@
         }
         catch (Exception e)
         {
-            throw new RuntimeException(String.format("Unexpected exception on attempt to retrieve state from '%s' at '%s'",
-                    helperNodeName, helperHostPort), e);
+            throw new RuntimeException(String.format("Cannot retrieve state for node '%s' (%s) from group '%s'",
+                    helperNodeName, helperHostPort, groupName), e);
         }
 
         if (LOGGER.isDebugEnabled())
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java b/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java
index e610995..0003e74 100644
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java
+++ b/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java
@@ -20,7 +20,11 @@
  */
 package org.apache.qpid.server.virtualhostnode.berkeleydb;
 
+import java.io.File;
 import java.net.InetSocketAddress;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
 import java.security.PrivilegedAction;
 import java.text.MessageFormat;
 import java.util.ArrayList;
@@ -74,6 +78,7 @@
 import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacade;
 import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacadeFactory;
 import org.apache.qpid.server.store.berkeleydb.replication.ReplicationGroupListener;
+import org.apache.qpid.server.util.PortUtil;
 import org.apache.qpid.server.util.ServerScopedRuntimeException;
 import org.apache.qpid.server.virtualhost.berkeleydb.BDBHAVirtualHostImpl;
 import org.apache.qpid.server.virtualhostnode.AbstractVirtualHostNode;
@@ -255,7 +260,7 @@
     public String toString()
     {
         return "BDBHAVirtualHostNodeImpl [id=" + getId() + ", name=" + getName() + ", storePath=" + _storePath + ", groupName=" + _groupName + ", address=" + _address
-                + ", state=" + getState() + ", priority=" + _priority + ", designatedPrimary=" + _designatedPrimary + ", quorumOverride=" + _quorumOverride + "]";
+                + ", state=" + getState() + ", priority=" + _priority + ", designatedPrimary=" + _designatedPrimary + ", quorumOverride=" + _quorumOverride + ", role=" + getRole() + "]";
     }
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
@@ -282,22 +287,18 @@
         super.onCreate();
         if (!isFirstNodeInAGroup())
         {
-            try
-            {
-                int dbPingSocketTimeout = getContextKeys(false).contains("qpid.bdb.ha.db_ping_socket_timeout") ? getContextValue(Integer.class, "qpid.bdb.ha.db_ping_socket_timeout") : 10000 /* JE's own default */;
-                Collection<String> permittedNodes = ReplicatedEnvironmentFacade.connectToHelperNodeAndCheckPermittedHosts(getName(), getAddress(), getGroupName(), getHelperNodeName(), getHelperAddress(), dbPingSocketTimeout);
-                setAttribute(PERMITTED_NODES, null, new ArrayList<String>(permittedNodes));
-            }
-            catch(IllegalConfigurationException e)
-            {
-                deleted();
-                throw e;
-            }
+            _permittedNodes = new ArrayList<>(getPermittedNodesFromHelper());
         }
-
         getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.CREATED());
     }
 
+    @Override
+    public void onOpen()
+    {
+        validatePermittedNodesFormat(_permittedNodes);
+        super.onOpen();
+    }
+
     protected ReplicatedEnvironmentFacade getReplicatedEnvironmentFacade()
     {
         return _environmentFacade.get();
@@ -334,6 +335,24 @@
             throw new IllegalStateException("Environment facade is not created");
         }
 
+        try
+        {
+            Set<ReplicationNode> remoteNodes = environmentFacade.getEnvironment().getGroup().getNodes();
+            for (ReplicationNode node : remoteNodes)
+            {
+                String nodeAddress = node.getHostName() + ":" + node.getPort();
+                if (!_permittedNodes.contains(nodeAddress))
+                {
+                    shutdownOnIntruder(nodeAddress);
+                    throw new IllegalStateException("Intruder node detected: " + nodeAddress);
+                }
+            }
+        }
+        catch (DatabaseException dbe)
+        {
+            environmentFacade.handleDatabaseException("DB exception while checking for intruder node", dbe);
+        }
+
         if (_environmentFacade.compareAndSet(null, environmentFacade))
         {
             environmentFacade.setStateChangeListener(new EnvironmentStateChangeListener());
@@ -372,9 +391,15 @@
     @StateTransition( currentState = { State.ACTIVE, State.STOPPED, State.ERRORED}, desiredState = State.DELETED )
     protected void doDelete()
     {
+        // get helpers before close. on close all children are closed and not available anymore
         Set<InetSocketAddress> helpers = getRemoteNodeAddresses();
         super.doDelete();
-        getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.DELETED());
+
+        if (getConfigurationStore() != null)
+        {
+            getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.DELETED());
+        }
+
         if (getState() == State.DELETED && !helpers.isEmpty())
         {
             try
@@ -432,20 +457,87 @@
     }
 
     @Override
-    public void onValidate()
+    protected void postResolve()
     {
-        super.onValidate();
+        super.postResolve();
         _virtualHostNodeLogSubject =  new BDBHAVirtualHostNodeLogSubject(getGroupName(), getName());
         _groupLogSubject = new GroupLogSubject(getGroupName());
         _virtualHostNodePrincipalName = MessageFormat.format(VIRTUAL_HOST_PRINCIPAL_NAME_FORMAT, getGroupName(), getName());
     }
 
     @Override
-    public  void onOpen()
+    public void validateOnCreate()
     {
-        super.onOpen();
+        super.validateOnCreate();
 
-        validatePermittedNodes(_permittedNodes);
+        validateAddress();
+
+        validateStorePath();
+
+        if (!isFirstNodeInAGroup())
+        {
+            getPermittedNodesFromHelper();
+        }
+    }
+
+    private Collection<String> getPermittedNodesFromHelper()
+    {
+        int dbPingSocketTimeout = getContextKeys(false).contains("qpid.bdb.ha.db_ping_socket_timeout") ? getContextValue(Integer.class, "qpid.bdb.ha.db_ping_socket_timeout") : 10000 /* JE's own default */;
+        return ReplicatedEnvironmentFacade.connectToHelperNodeAndCheckPermittedHosts(getName(), getAddress(), getGroupName(), getHelperNodeName(), getHelperAddress(), dbPingSocketTimeout);
+    }
+
+    private void validateStorePath()
+    {
+        File storePath = new File(getStorePath());
+        while (!storePath.exists())
+        {
+            storePath = storePath.getParentFile();
+            if (storePath == null)
+            {
+                throw new IllegalConfigurationException(String.format("Store path '%s' is invalid", getStorePath()));
+            }
+        }
+
+        if (!storePath.isDirectory())
+        {
+            throw new IllegalConfigurationException(String.format("Store path '%s' is not a folder", getStorePath()));
+        }
+
+        if (!Files.isWritable(storePath.toPath()))
+        {
+            throw new IllegalConfigurationException(String.format("Store path '%s' is not writable", getStorePath()));
+        }
+    }
+
+    private void validateAddress()
+    {
+        String address = getAddress();
+
+        URI uri = addressToURI(address);
+
+        if (!PortUtil.isPortAvailable(uri.getHost(), uri.getPort()))
+        {
+            throw new IllegalConfigurationException(String.format("Cannot bind to address '%s'. Address is already in use.", address));
+        }
+    }
+
+    private URI addressToURI(String address)
+    {
+        if (address == null || "".equals(address))
+        {
+            throw new IllegalConfigurationException("Node address is not set");
+        }
+
+        URI uri = null;
+        try
+        {
+            uri = new URI( "tcp://" + address);
+        }
+        catch (URISyntaxException e)
+        {
+            throw new IllegalConfigurationException(String.format("Invalid address specified '%s'. ", address));
+        }
+        return uri;
     }
 
     private void onMaster()
@@ -538,7 +630,7 @@
 
     private void onDetached()
     {
-        createReplicaVirtualHost();
+        closeVirtualHostIfExist();
     }
 
     private void createReplicaVirtualHost()
@@ -578,7 +670,7 @@
 
             if (LOGGER.isInfoEnabled())
             {
-                LOGGER.info("Received BDB event indicating transition to state " + state);
+                LOGGER.info("Received BDB event indicating transition to state " + state + " for " + getName());
             }
             NodeRole previousRole = getRole();
             try
@@ -728,7 +820,7 @@
 
     private boolean isFirstNodeInAGroup()
     {
-        return getAddress().equals(getHelperAddress());
+        return getHelperNodeName() == null;
     }
 
     BDBHAVirtualHostNodeLogSubject getVirtualHostNodeLogSubject()
@@ -761,7 +853,7 @@
         }
     }
 
-    private void validatePermittedNodes(List<String> proposedPermittedNodes)
+    private void validatePermittedNodes(Collection<String> proposedPermittedNodes)
     {
         if (getRemoteReplicationNodes().size() > 0 && getRole() != NodeRole.MASTER && !(getState() == State.STOPPED || getState() == State.ERRORED))
         {
@@ -772,47 +864,48 @@
             throw new IllegalArgumentException(String.format("Attribute '%s' is mandatory and must be set", PERMITTED_NODES));
         }
 
-        String missingNodeAddress = null;
-        if (getPermittedNodes().contains(getAddress()) && !proposedPermittedNodes.contains(getAddress()))
+        if (_permittedNodes != null)
         {
-            missingNodeAddress = getAddress();
-        }
-        else
-        {
-            for (final RemoteReplicationNode<?> node : getRemoteReplicationNodes())
+            String missingNodeAddress = null;
+
+            if (_permittedNodes.contains(getAddress()) && !proposedPermittedNodes.contains(getAddress()))
             {
-                final BDBHARemoteReplicationNode<?> bdbHaRemoteReplicationNode = (BDBHARemoteReplicationNode<?>) node;
-                final String remoteNodeAddress = bdbHaRemoteReplicationNode.getAddress();
-                if (getPermittedNodes().contains(remoteNodeAddress) && !proposedPermittedNodes.contains(remoteNodeAddress))
+                missingNodeAddress = getAddress();
+            }
+            else
+            {
+                for (final RemoteReplicationNode<?> node : getRemoteReplicationNodes())
                 {
-                    missingNodeAddress = remoteNodeAddress;
-                    break;
+                    final BDBHARemoteReplicationNode<?> bdbHaRemoteReplicationNode = (BDBHARemoteReplicationNode<?>) node;
+                    final String remoteNodeAddress = bdbHaRemoteReplicationNode.getAddress();
+                    if (_permittedNodes.contains(remoteNodeAddress) && !proposedPermittedNodes.contains(remoteNodeAddress))
+                    {
+                        missingNodeAddress = remoteNodeAddress;
+                        break;
+                    }
                 }
             }
+
+            if (missingNodeAddress != null)
+            {
+                throw new IllegalArgumentException(String.format("The current group node '%s' cannot be removed from '%s' as its already a group member", missingNodeAddress, PERMITTED_NODES));
+            }
         }
 
-        if (missingNodeAddress != null)
+        validatePermittedNodesFormat(proposedPermittedNodes);
+    }
+
+    private void validatePermittedNodesFormat(Collection<String> permittedNodes)
+    {
+        if (permittedNodes == null || permittedNodes.isEmpty())
         {
-            throw new IllegalArgumentException(String.format("The current group node '%s' cannot be removed from '%s' as its already a group member", missingNodeAddress, PERMITTED_NODES));
+            throw new IllegalConfigurationException("Permitted nodes are not set");
         }
 
-        for (String permittedNode: proposedPermittedNodes)
+        for (String permittedNode: permittedNodes)
         {
-            String[] tokens = permittedNode.split(":");
-            if (tokens.length != 2)
-            {
-                throw new IllegalArgumentException(String.format("Invalid permitted node specified '%s'. ", permittedNode));
-            }
-            try
-            {
-                Integer.parseInt(tokens[1]);
-            }
-            catch(Exception e)
-            {
-                throw new IllegalArgumentException(String.format("Invalid port is specified in permitted node '%s'. ", permittedNode));
-            }
+            addressToURI(permittedNode);
         }
-
     }
 
     private class RemoteNodesDiscoverer implements ReplicationGroupListener
@@ -931,7 +1024,7 @@
                     {
                         byte[] applicationState = nodeState.getAppState();
                         Set<String> permittedNodes = ReplicatedEnvironmentFacade.convertApplicationStateBytesToPermittedNodeList(applicationState);
-                        if (!_permittedNodes.equals(permittedNodes))
+                        if (_permittedNodes.size() != permittedNodes.size() || !_permittedNodes.containsAll(permittedNodes))
                         {
                             if (_permittedNodes.contains(remoteNode.getAddress()))
                             {
@@ -972,7 +1065,7 @@
 
         private boolean processIntruderNode(ReplicationNode node)
         {
-            String hostAndPort = node.getHostName() + ":" + node.getPort();
+            final String hostAndPort = node.getHostName() + ":" + node.getPort();
             getEventLogger().message(getGroupLogSubject(), HighAvailabilityMessages.INTRUDER_DETECTED(node.getName(), hostAndPort));
 
             boolean inManagementMode = getParent(Broker.class).isManagementMode();
@@ -994,35 +1087,16 @@
                                            BDBHAVirtualHostNodeImpl.this.getName(),
                                            _lastRole.get(),
                                            String.valueOf(BDBHAVirtualHostNodeImpl.this.getPermittedNodes()) ));
-
                 getTaskExecutor().submit(new Task<Void>()
                 {
                     @Override
                     public Void execute()
                     {
-                        State state = getState();
-                        if (state != State.ERRORED)
-                        {
-                            try
-                            {
-                                stopAndSetStateTo(State.ERRORED);
-                            }
-                            catch(Exception e)
-                            {
-                                LOGGER.error("Unexpected exception on closing the node when intruder is detected ", e);
-                            }
-                            finally
-                            {
-                                closeEnvironment();
-
-                                _lastRole.set(NodeRole.DETACHED);
-                                attributeSet(ROLE, _role, NodeRole.DETACHED);
-                            }
-                            notifyStateChanged(state, State.ERRORED);
-                        }
+                        shutdownOnIntruder(hostAndPort);
                         return null;
                     }
                 });
+
                 return false;
             }
         }
@@ -1044,6 +1118,28 @@
         }
     }
 
+    protected void shutdownOnIntruder(String intruderHostAndPort)
+    {
+        LOGGER.info("Intruder detected (" + intruderHostAndPort + "), stopping and setting state to ERRORED");
+
+        State initialState = getState();
+        try
+        {
+            stopAndSetStateTo(State.ERRORED);
+        }
+        catch (Exception e)
+        {
+            LOGGER.error("Unexpected exception on closing the node when intruder is detected ", e);
+        }
+        finally
+        {
+            closeEnvironment();
+            _lastRole.set(NodeRole.DETACHED);
+            attributeSet(ROLE, _role, NodeRole.DETACHED);
+        }
+        notifyStateChanged(initialState, State.ERRORED);
+    }
+
     private abstract class VirtualHostNodeGroupTask implements Task<Void>
     {
         @Override
diff --git a/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/newgroup/add.js b/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/newgroup/add.js
index 18853e6..464a01b 100644
--- a/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/newgroup/add.js
+++ b/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/newgroup/add.js
@@ -106,6 +106,7 @@
         _changeAddress: function(address, virtualHostNodeHelperAddress)
         {
           virtualHostNodeHelperAddress.set("value", address);
+          this._updatePermittedNodesJson();
         },
         _clickAddPermittedNodeButton: function(e)
         {
diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java
index e9bcc5d..ee990d3 100644
--- a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java
+++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java
@@ -23,13 +23,17 @@
 import static org.mockito.Mockito.when;
 
 import java.io.File;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 
 import com.sleepycat.je.Durability;
@@ -38,12 +42,14 @@
 import com.sleepycat.je.rep.ReplicationConfig;
 
 import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.model.AbstractConfiguredObject;
 import org.apache.qpid.server.model.ConfigurationChangeListener;
 import org.apache.qpid.server.model.ConfiguredObject;
 import org.apache.qpid.server.model.RemoteReplicationNode;
 import org.apache.qpid.server.model.State;
 import org.apache.qpid.server.model.VirtualHost;
 import org.apache.qpid.server.store.DurableConfigurationStore;
+import org.apache.qpid.server.store.berkeleydb.replication.DatabasePinger;
 import org.apache.qpid.server.virtualhost.berkeleydb.BDBHAVirtualHost;
 import org.apache.qpid.server.virtualhost.berkeleydb.BDBHAVirtualHostImpl;
 import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHARemoteReplicationNode;
@@ -53,6 +59,8 @@
 import org.apache.qpid.server.virtualhostnode.berkeleydb.NodeRole;
 import org.apache.qpid.test.utils.PortHelper;
 import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.test.utils.TestFileUtils;
+import org.apache.qpid.util.FileUtils;
 
 public class BDBHAVirtualHostNodeTest extends QpidTestCase
 {
@@ -289,6 +297,7 @@
         _helper.awaitRemoteNodes(master, 2);
 
         BDBHAVirtualHostNode<?> replica = _helper.awaitAndFindNodeInRole(NodeRole.REPLICA);
+        _helper.awaitRemoteNodes(replica, 2);
 
         assertNotNull("Remote node " + replica.getName() + " is not found", _helper.findRemoteNode(master, replica.getName()));
         replica.delete();
@@ -481,8 +490,100 @@
         nonMasterNode.setAttributes(Collections.<String, Object>singletonMap(BDBHAVirtualHostNode.PERMITTED_NODES, amendedPermittedNodes));
     }
 
+    public void testIntruderProtection() throws Exception
+    {
+        int nodePortNumber = _portHelper.getNextAvailable();
+        int intruderPortNumber = _portHelper.getNextAvailable();
+
+        String helperAddress = "localhost:" + nodePortNumber;
+        String groupName = "group";
+        String nodeName = "node";
+
+        Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, nodePortNumber, intruderPortNumber);
+        BDBHAVirtualHostNode<?> node = _helper.createAndStartHaVHN(node1Attributes);
+
+        Map<String, Object> intruderAttributes = _helper.createNodeAttributes("intruder", groupName, "localhost:" + intruderPortNumber, helperAddress, nodeName);
+        intruderAttributes.put(BDBHAVirtualHostNode.PRIORITY, 0);
+        BDBHAVirtualHostNode<?> intruder = _helper.createAndStartHaVHN(intruderAttributes);
+
+        final CountDownLatch stopLatch = new CountDownLatch(1);
+        ConfigurationChangeListener listener = new NoopConfigurationChangeListener()
+        {
+            @Override
+            public void stateChanged(ConfiguredObject<?> object, State oldState, State newState)
+            {
+                if (newState == State.ERRORED)
+                {
+                    stopLatch.countDown();
+                }
+            }
+        };
+        node.addChangeListener(listener);
+
+        List<String> permittedNodes = new ArrayList<String>();
+        permittedNodes.add(helperAddress);
+        node.setAttributes(Collections.<String, Object>singletonMap(BDBHAVirtualHostNode.PERMITTED_NODES, permittedNodes));
+
+        assertTrue("Intruder protection was not triggered during expected timeout", stopLatch.await(10, TimeUnit.SECONDS));
+
+        // Try top re start the ERRORED node and ensure exception is thrown
+        try
+        {
+            node.start();
+            fail("Restart of node should have thrown exception");
+        }
+        catch (IllegalStateException ise)
+        {
+            assertEquals("Unexpected exception when restarting node post intruder detection", "Intruder node detected: " + "localhost:" + intruderPortNumber, ise.getMessage());
+        }
+        _helper.awaitForAttributeChange(node, AbstractConfiguredObject.STATE, State.ERRORED);
+    }
+
     public void testIntruderProtectionInManagementMode() throws Exception
     {
+        int nodePortNumber = _portHelper.getNextAvailable();
+        int intruderPortNumber = _portHelper.getNextAvailable();
+
+        String helperAddress = "localhost:" + nodePortNumber;
+        String groupName = "group";
+        String nodeName = "node";
+
+        Map<String, Object> nodeAttributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, nodePortNumber, intruderPortNumber);
+        BDBHAVirtualHostNode<?> node = _helper.createAndStartHaVHN(nodeAttributes);
+
+        Map<String, Object> intruderAttributes = _helper.createNodeAttributes("intruder", groupName, "localhost:" + intruderPortNumber, helperAddress, nodeName);
+        intruderAttributes.put(BDBHAVirtualHostNode.PRIORITY, 0);
+        BDBHAVirtualHostNode<?> intruder = _helper.createAndStartHaVHN(intruderAttributes);
+
+        final CountDownLatch stopLatch = new CountDownLatch(1);
+        ConfigurationChangeListener listener = new NoopConfigurationChangeListener()
+        {
+            @Override
+            public void stateChanged(ConfiguredObject<?> object, State oldState, State newState)
+            {
+                if (newState == State.ERRORED)
+                {
+                    stopLatch.countDown();
+                }
+            }
+        };
+        node.addChangeListener(listener);
+
+        List<String> permittedNodes = new ArrayList<String>();
+        permittedNodes.add(helperAddress);
+        node.setAttributes(Collections.<String, Object>singletonMap(BDBHAVirtualHostNode.PERMITTED_NODES, permittedNodes));
+
+        assertTrue("Intruder protection was not triggered during expected timeout", stopLatch.await(10, TimeUnit.SECONDS));
+
+        // test that if management mode is enabled then the node can start without exception
+        when(_helper.getBroker().isManagementMode()).thenReturn(true);
+        node.start();
+
+        _helper.awaitForAttributeChange(node, AbstractConfiguredObject.STATE, State.ERRORED);
+    }
+
+    public void testPermittedNodesChangedOnReplicaNodeOnlyOnceAfterBeingChangedOnMaster() throws Exception
+    {
         int node1PortNumber = _portHelper.getNextAvailable();
         int node2PortNumber = _portHelper.getNextAvailable();
 
@@ -496,34 +597,55 @@
         Map<String, Object> node2Attributes = _helper.createNodeAttributes("node2", groupName, "localhost:" + node2PortNumber, helperAddress, nodeName);
         node2Attributes.put(BDBHAVirtualHostNode.PRIORITY, 0);
         BDBHAVirtualHostNode<?> node2 = _helper.createAndStartHaVHN(node2Attributes);
+        assertEquals("Unexpected role", NodeRole.REPLICA, node2.getRole());
+        _helper.awaitRemoteNodes(node2, 1);
 
-        final CountDownLatch stopLatch = new CountDownLatch(1);
-        ConfigurationChangeListener listener = new NoopConfigurationChangeListener()
+        BDBHARemoteReplicationNode<?> remote = _helper.findRemoteNode(node2, node1.getName());
+
+        final AtomicInteger permittedNodesChangeCounter = new AtomicInteger();
+        final CountDownLatch _permittedNodesLatch = new CountDownLatch(1);
+        node2.addChangeListener(new NoopConfigurationChangeListener()
         {
             @Override
-            public void stateChanged(ConfiguredObject<?> object, State oldState, State newState)
+            public void attributeSet(ConfiguredObject<?> object, String attributeName, Object oldAttributeValue, Object newAttributeValue)
             {
-                if (newState == State.ERRORED)
+                if (attributeName.equals(BDBHAVirtualHostNode.PERMITTED_NODES))
                 {
-                    stopLatch.countDown();
+                    permittedNodesChangeCounter.incrementAndGet();
+                    _permittedNodesLatch.countDown();
                 }
             }
-        };
-        node1.addChangeListener(listener);
-
-        List<String> permittedNodes = new ArrayList<String>();
-        permittedNodes.add(helperAddress);
+        });
+        List<String> permittedNodes = new ArrayList<>(node1.getPermittedNodes());
+        permittedNodes.add("localhost:5000");
         node1.setAttributes(Collections.<String, Object>singletonMap(BDBHAVirtualHostNode.PERMITTED_NODES, permittedNodes));
 
-        assertTrue("Intruder protection was not triggered during expected timeout", stopLatch.await(10, TimeUnit.SECONDS));
+        assertTrue("Permitted nodes were not changed on Replica", _permittedNodesLatch.await(10, TimeUnit.SECONDS));
+        assertEquals("Not the same permitted nodes", new HashSet<>(node1.getPermittedNodes()), new HashSet<>(node2.getPermittedNodes()));
+        assertEquals("Unexpected counter of changes permitted nodes", 1, permittedNodesChangeCounter.get());
 
-        when(_helper.getBroker().isManagementMode()).thenReturn(true);
-        node1.start();
+        // change the order of permitted nodes
+        Collections.swap(permittedNodes, 0, 2);
+        node1.setAttributes(Collections.<String, Object>singletonMap(BDBHAVirtualHostNode.PERMITTED_NODES, permittedNodes));
 
-        _helper.awaitRemoteNodes(node1, 1);
+        // make sure that node2 onNodeState was invoked by performing transaction on master and making sure that it was replicated
+        performTransactionAndAwaitForRemoteNodeToGetAware(node1, remote);
 
-        BDBHARemoteReplicationNode<?> remote = _helper.findRemoteNode(node1, node2.getName());
-        remote.delete();
+        // perform transaction second time because permitted nodes are changed after last transaction id
+        performTransactionAndAwaitForRemoteNodeToGetAware(node1, remote);
+        assertEquals("Unexpected counter of changes permitted nodes", 1, permittedNodesChangeCounter.get());
+    }
+
+    private void performTransactionAndAwaitForRemoteNodeToGetAware(BDBHAVirtualHostNode<?> node1, BDBHARemoteReplicationNode<?> remote) throws InterruptedException
+    {
+        new DatabasePinger().pingDb(((BDBConfigurationStore)node1.getConfigurationStore()).getEnvironmentFacade());
+
+        int waitCounter = 100;
+        while ( remote.getLastKnownReplicationTransactionId() != node1.getLastKnownReplicationTransactionId() && (waitCounter--) != 0)
+        {
+            Thread.sleep(100l);
+        }
+        assertEquals("Last transaction was not replicated", new Long(remote.getLastKnownReplicationTransactionId()), node1.getLastKnownReplicationTransactionId() );
     }
 
     public void testIntruderConnected() throws Exception
@@ -587,4 +709,87 @@
         assertTrue("Intruder protection was not triggered during expected timeout", stopLatch.await(20, TimeUnit.SECONDS));
     }
 
+    public void testValidateOnCreateForNonExistingHelperNode() throws Exception
+    {
+        int node1PortNumber = findFreePort();
+        int node2PortNumber = getNextAvailable(node1PortNumber + 1);
+
+
+        Map<String, Object> attributes = _helper.createNodeAttributes("node1", "group", "localhost:" + node1PortNumber,
+                "localhost:" + node2PortNumber, "node2", node1PortNumber, node1PortNumber, node2PortNumber);
+        try
+        {
+            _helper.createAndStartHaVHN(attributes);
+            fail("Node creation should fail because of invalid helper address");
+        }
+        catch(IllegalConfigurationException e)
+        {
+            assertEquals("Unexpected exception on connection to non-existing helper address",
+                    String.format("Cannot connect to existing node '%s' at '%s'", "node2", "localhost:" + node2PortNumber), e.getMessage());
+        }
+    }
+
+    public void testValidateOnCreateForAlreadyBoundAddress() throws Exception
+    {
+        int node1PortNumber = findFreePort();
+
+        ServerSocket serverSocket = null;
+        try
+        {
+            serverSocket = new ServerSocket();
+            serverSocket.setReuseAddress(true);
+            serverSocket.bind(new InetSocketAddress("localhost", node1PortNumber));
+
+
+            Map<String, Object> attributes = _helper.createNodeAttributes("node1", "group", "localhost:" + node1PortNumber,
+                    "localhost:" + node1PortNumber, "node2", node1PortNumber, node1PortNumber);
+            try
+            {
+                _helper.createAndStartHaVHN(attributes);
+                fail("Node creation should fail because of invalid address");
+            }
+            catch(IllegalConfigurationException e)
+            {
+                assertEquals("Unexpected exception on attempt to create node with already bound address",
+                        String.format("Cannot bind to address '%s'. Address is already in use.", "localhost:" + node1PortNumber), e.getMessage());
+            }
+        }
+        finally
+        {
+            if (serverSocket != null)
+            {
+                serverSocket.close();
+            }
+        }
+    }
+
+    public void testValidateOnCreateForInvalidStorePath() throws Exception
+    {
+        int node1PortNumber = findFreePort();
+
+        File storeBaseFolder = TestFileUtils.createTestDirectory();
+        File file = new File(storeBaseFolder, getTestName());
+        file.createNewFile();
+        File storePath = new File(file, "test");
+        try
+        {
+            Map<String, Object> attributes = _helper.createNodeAttributes("node1", "group", "localhost:" + node1PortNumber,
+                    "localhost:" + node1PortNumber, "node2", node1PortNumber, node1PortNumber);
+            attributes.put(BDBHAVirtualHostNode.STORE_PATH, storePath.getAbsoluteFile());
+            try
+            {
+                _helper.createAndStartHaVHN(attributes);
+                fail("Node creation should fail because of invalid store path");
+            }
+            catch (IllegalConfigurationException e)
+            {
+                assertEquals("Unexpected exception on attempt to create environment in invalid location",
+                        String.format("Store path '%s' is not a folder", storePath.getAbsoluteFile()), e.getMessage());
+            }
+        }
+        finally
+        {
+            FileUtils.delete(storeBaseFolder, true);
+        }
+    }
 }
diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBVirtualHostImplTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBVirtualHostImplTest.java
new file mode 100644
index 0000000..92da465
--- /dev/null
+++ b/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBVirtualHostImplTest.java
@@ -0,0 +1,106 @@
+/*
+ *
+ * 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.server.virtualhost.berkeleydb;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
+import org.apache.qpid.server.configuration.updater.TaskExecutor;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.VirtualHostNode;
+import org.apache.qpid.server.store.DurableConfigurationStore;
+import org.apache.qpid.server.util.BrokerTestHelper;
+import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.test.utils.TestFileUtils;
+import org.apache.qpid.util.FileUtils;
+
+public class BDBVirtualHostImplTest extends QpidTestCase
+{
+    private File _storePath;
+    private VirtualHostNode<?> _node;
+
+    @Override
+    public void setUp() throws Exception
+    {
+        super.setUp();
+        Broker broker = BrokerTestHelper.createBrokerMock();
+
+        TaskExecutor taskExecutor = CurrentThreadTaskExecutor.newStartedInstance();
+        when(broker.getTaskExecutor()).thenReturn(taskExecutor);
+
+        _storePath = TestFileUtils.createTestDirectory();
+
+        _node = mock(VirtualHostNode.class);
+        when(_node.getParent(Broker.class)).thenReturn(broker);
+        when(_node.getModel()).thenReturn(BrokerModel.getInstance());
+        when(_node.getTaskExecutor()).thenReturn(taskExecutor);
+        when(_node.getConfigurationStore()).thenReturn(mock(DurableConfigurationStore.class));
+        when(_node.getId()).thenReturn(UUID.randomUUID());
+    }
+
+    @Override
+    public void  tearDown() throws Exception
+    {
+        try
+        {
+            if (_storePath != null)
+            {
+                FileUtils.delete(_storePath, true);
+            }
+        }
+        finally
+        {
+            super.tearDown();
+        }
+    }
+
+    public void testValidateOnCreateForInvalidStorePath() throws Exception
+    {
+        String hostName = getTestName();
+        File file = new File(_storePath + File.separator + hostName);
+        assertTrue("Empty file is not created", file.createNewFile());
+        Map<String, Object> attributes = new HashMap<>();
+        attributes.put(BDBVirtualHost.ID, UUID.randomUUID());
+        attributes.put(BDBVirtualHost.TYPE, BDBVirtualHostImpl.VIRTUAL_HOST_TYPE);
+        attributes.put(BDBVirtualHost.NAME, hostName);
+        attributes.put(BDBVirtualHost.STORE_PATH, file.getAbsoluteFile());
+
+        BDBVirtualHostImpl host = new BDBVirtualHostImpl(attributes, _node);
+        try
+        {
+            host.create();
+            fail("Cannot create DBD virtual host from existing empty file");
+        }
+        catch (IllegalConfigurationException e)
+        {
+            assertTrue("Unexpected exception " + e.getMessage(), e.getMessage().startsWith("Cannot open virtual host message store"));
+        }
+    }
+
+}
diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeOperationalLoggingTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeOperationalLoggingTest.java
index d71fb8b..6d74056 100644
--- a/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeOperationalLoggingTest.java
+++ b/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeOperationalLoggingTest.java
@@ -87,6 +87,9 @@
 
         _helper.assertNodeRole(node1, NodeRole.MASTER);
 
+        // stop node to avoid running into race when role change is reported after we performed the check
+        node1.stop();
+
         assertEquals("Unexpected VHN log subject", "[grp(/group)/vhn(/node1)] ", node1.getVirtualHostNodeLogSubject().getLogString());
         assertEquals("Unexpected group log subject", "[grp(/group)] ", node1.getGroupLogSubject().getLogString());
 
diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeTestHelper.java b/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeTestHelper.java
index c12fece..0dc72ac 100644
--- a/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeTestHelper.java
+++ b/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeTestHelper.java
@@ -279,11 +279,14 @@
         node1Attributes.put(BDBHAVirtualHostNode.ADDRESS, address);
         node1Attributes.put(BDBHAVirtualHostNode.HELPER_ADDRESS, helperAddress);
         node1Attributes.put(BDBHAVirtualHostNode.STORE_PATH, getMessageStorePath() + File.separator + nodeName);
-        node1Attributes.put(BDBHAVirtualHostNode.HELPER_NODE_NAME, helperNodeNode);
         if (address.equals(helperAddress))
         {
             node1Attributes.put(BDBHAVirtualHostNode.PERMITTED_NODES, getPermittedNodes(ports));
         }
+        else
+        {
+            node1Attributes.put(BDBHAVirtualHostNode.HELPER_NODE_NAME, helperNodeNode);
+        }
 
         Map<String, String> context = new HashMap<String, String>();
         context.put(ReplicationConfig.REPLICA_ACK_TIMEOUT, "2 s");
diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNodeTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNodeTest.java
new file mode 100644
index 0000000..6608312
--- /dev/null
+++ b/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNodeTest.java
@@ -0,0 +1,92 @@
+/*
+ *
+ * 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.server.virtualhostnode.berkeleydb;
+
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.util.BrokerTestHelper;
+import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.test.utils.TestFileUtils;
+import org.apache.qpid.util.FileUtils;
+
+public class BDBVirtualHostNodeTest extends QpidTestCase
+{
+    private Broker<?> _broker;
+    private File _storePath;
+
+    @Override
+    public void setUp() throws Exception
+    {
+        super.setUp();
+        _broker = BrokerTestHelper.createBrokerMock();
+        when(_broker.getTaskExecutor()).thenReturn(CurrentThreadTaskExecutor.newStartedInstance());
+
+        _storePath = TestFileUtils.createTestDirectory();
+    }
+
+    @Override
+    public void  tearDown() throws Exception
+    {
+        try
+        {
+            if (_storePath != null)
+            {
+                FileUtils.delete(_storePath, true);
+            }
+        }
+        finally
+        {
+            super.tearDown();
+        }
+    }
+
+    public void testValidateOnCreateForInvalidStorePath() throws Exception
+    {
+        String nodeName = getTestName();
+        File file = new File(_storePath + File.separator + nodeName);
+        assertTrue("Empty file is not created", file.createNewFile());
+        Map<String, Object> attributes = new HashMap<>();
+        attributes.put(BDBVirtualHostNode.ID, UUID.randomUUID());
+        attributes.put(BDBVirtualHostNode.TYPE, BDBVirtualHostNodeImpl.VIRTUAL_HOST_NODE_TYPE);
+        attributes.put(BDBVirtualHostNode.NAME, nodeName);
+        attributes.put(BDBVirtualHostNode.STORE_PATH, file.getAbsolutePath());
+
+        BDBVirtualHostNodeImpl node = new BDBVirtualHostNodeImpl(attributes, _broker);
+        try
+        {
+            node.create();
+            fail("Cannot create DBD node from existing empty file");
+        }
+        catch (IllegalConfigurationException e)
+        {
+            assertTrue("Unexpected exception " + e.getMessage(), e.getMessage().startsWith("Cannot open node configuration store"));
+        }
+    }
+
+}
diff --git a/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/BDBHAVirtualHostNodeRestTest.java b/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/BDBHAVirtualHostNodeRestTest.java
index c0c1b23..cfbd030 100644
--- a/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/BDBHAVirtualHostNodeRestTest.java
+++ b/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/BDBHAVirtualHostNodeRestTest.java
@@ -326,7 +326,10 @@
         nodeData.put(BDBHAVirtualHostNode.GROUP_NAME, _hostName);
         nodeData.put(BDBHAVirtualHostNode.ADDRESS, "localhost:" + nodePort);
         nodeData.put(BDBHAVirtualHostNode.HELPER_ADDRESS, "localhost:" + helperPort);
-        nodeData.put(BDBHAVirtualHostNode.HELPER_NODE_NAME, NODE1);
+        if (nodePort != helperPort)
+        {
+            nodeData.put(BDBHAVirtualHostNode.HELPER_NODE_NAME, NODE1);
+        }
 
         Map<String,String> context = new HashMap<>();
         nodeData.put(BDBHAVirtualHostNode.CONTEXT, context);
diff --git a/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/MultiNodeTest.java b/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/MultiNodeTest.java
index 9e85071..38484b5 100644
--- a/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/MultiNodeTest.java
+++ b/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/MultiNodeTest.java
@@ -166,8 +166,8 @@
         // New connections should now fail as vhost will be unavailable
         try
         {
-            getConnection(_negativeFailoverUrl);
-            fail("Exception not thrown");
+            Connection unexpectedConnection = getConnection(_negativeFailoverUrl);
+            fail("Got unexpected connection to node in group without quorum " + unexpectedConnection);
         }
         catch (JMSException je)
         {
diff --git a/java/broker-codegen/src/main/java/org/apache/qpid/server/model/SystemConfigFactoryGenerator.java b/java/broker-codegen/src/main/java/org/apache/qpid/server/model/SystemConfigFactoryGenerator.java
index c569bc4..317e0f7 100644
--- a/java/broker-codegen/src/main/java/org/apache/qpid/server/model/SystemConfigFactoryGenerator.java
+++ b/java/broker-codegen/src/main/java/org/apache/qpid/server/model/SystemConfigFactoryGenerator.java
@@ -117,9 +117,9 @@
             pw.println("import org.apache.qpid.server.configuration.updater.TaskExecutor;");
             pw.println("import org.apache.qpid.server.logging.EventLogger;");
             pw.println("import org.apache.qpid.server.logging.LogRecorder;");
-            pw.println("import org.apache.qpid.server.model.SystemConfig;");
+            pw.println("import org.apache.qpid.server.model.BrokerShutdownProvider;");
             pw.println("import org.apache.qpid.server.model.ConfiguredObjectTypeRegistry;");
-            pw.println();
+            pw.println("import org.apache.qpid.server.model.SystemConfig;");
             pw.println("import org.apache.qpid.server.plugin.PluggableService;");
             pw.println("import org.apache.qpid.server.plugin.SystemConfigFactory;");
             pw.println();
@@ -140,9 +140,10 @@
             pw.println("    public "+objectSimpleName+" newInstance(final TaskExecutor taskExecutor,");
             pw.println("                       final EventLogger eventLogger,");
             pw.println("                       final LogRecorder logRecorder,");
-            pw.println("                       final BrokerOptions brokerOptions)");
+            pw.println("                       final BrokerOptions brokerOptions,");
+            pw.println("                       final BrokerShutdownProvider brokerShutdownProvider)");
             pw.println("    {");
-            pw.println("        return new "+objectSimpleName+"(taskExecutor, eventLogger, logRecorder, brokerOptions);");
+            pw.println("        return new "+objectSimpleName+"(taskExecutor, eventLogger, logRecorder, brokerOptions, brokerShutdownProvider);");
             pw.println("    }");
             pw.println("}");
 
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java b/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java
index 0a19791..0b925d1 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java
@@ -40,6 +40,7 @@
 import org.apache.qpid.server.logging.SystemOutMessageLogger;
 import org.apache.qpid.server.logging.log4j.LoggingManagementFacade;
 import org.apache.qpid.server.logging.messages.BrokerMessages;
+import org.apache.qpid.server.model.BrokerShutdownProvider;
 import org.apache.qpid.server.model.SystemConfig;
 import org.apache.qpid.server.plugin.PluggableFactoryLoader;
 import org.apache.qpid.server.plugin.SystemConfigFactory;
@@ -48,7 +49,7 @@
 import org.apache.qpid.server.security.SecurityManager;
 import org.apache.qpid.server.store.DurableConfigurationStore;
 
-public class Broker
+public class Broker implements BrokerShutdownProvider
 {
     private static final Logger LOGGER = Logger.getLogger(Broker.class);
 
@@ -143,7 +144,7 @@
         LogRecorder logRecorder = new LogRecorder();
 
         _taskExecutor.start();
-        SystemConfig systemConfig = configFactory.newInstance(_taskExecutor, _eventLogger, logRecorder, options);
+        SystemConfig systemConfig = configFactory.newInstance(_taskExecutor, _eventLogger, logRecorder, options, this);
         systemConfig.open();
         DurableConfigurationStore store = systemConfig.getConfigurationStore();
 
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/binding/BindingImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/binding/BindingImpl.java
index b71d667..6c67a44 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/binding/BindingImpl.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/binding/BindingImpl.java
@@ -29,9 +29,12 @@
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
 
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
 import org.apache.qpid.server.configuration.updater.VoidTask;
 import org.apache.qpid.server.exchange.AbstractExchange;
 import org.apache.qpid.server.exchange.ExchangeImpl;
+import org.apache.qpid.server.filter.AMQInvalidArgumentException;
+import org.apache.qpid.server.filter.FilterSupport;
 import org.apache.qpid.server.logging.EventLogger;
 import org.apache.qpid.server.logging.messages.BindingMessages;
 import org.apache.qpid.server.logging.subjects.BindingLogSubject;
@@ -269,4 +272,23 @@
                );
 
     }
+
+    @Override
+    public void validateOnCreate()
+    {
+        AMQQueue queue = getAMQQueue();
+        Map<String, Object> arguments = getArguments();
+        if (arguments!=null && !arguments.isEmpty() && FilterSupport.argumentsContainFilter(arguments))
+        {
+            try
+            {
+                FilterSupport.createMessageFilter(arguments, queue);
+            }
+            catch (AMQInvalidArgumentException e)
+            {
+                throw new IllegalConfigurationException(e.getMessage(), e);
+            }
+        }
+    }
+
 }
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java b/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
index fd0333f..989a4ab 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
@@ -118,16 +118,6 @@
             throw new IllegalArgumentException("Unknown attributes provided: " + providedAttributeNames);
         }
         _virtualHost = vhost;
-        // check ACL
-        try
-        {
-            _virtualHost.getSecurityManager().authoriseCreateExchange(this);
-        }
-        catch (AccessControlException e)
-        {
-            deleted();
-            throw e;
-        }
 
         _logSubject = new ExchangeLogSubject(this, this.getVirtualHost());
 
@@ -145,6 +135,12 @@
     }
 
     @Override
+    public void validateOnCreate()
+    {
+        _virtualHost.getSecurityManager().authoriseCreateExchange(this);
+    }
+
+    @Override
     public void onValidate()
     {
         super.onValidate();
@@ -756,7 +752,7 @@
                                              final Map<String, Object> oldArguments);
 
 
-    @StateTransition(currentState = State.UNINITIALIZED, desiredState = State.ACTIVE)
+    @StateTransition(currentState = {State.UNINITIALIZED,State.ERRORED}, desiredState = State.ACTIVE)
     private void activate()
     {
         setState(State.ACTIVE);
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
index d3741cd..e6f79fe 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
@@ -47,6 +47,7 @@
 
 import javax.security.auth.Subject;
 
+import org.apache.log4j.Logger;
 import org.codehaus.jackson.JsonGenerator;
 import org.codehaus.jackson.JsonProcessingException;
 import org.codehaus.jackson.Version;
@@ -72,6 +73,8 @@
 
 public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> implements ConfiguredObject<X>
 {
+    private static final Logger LOGGER = Logger.getLogger(AbstractConfiguredObject.class);
+
     private static final Map<Class, Object> SECURE_VALUES;
 
     public static final String SECURED_STRING_VALUE = "********";
@@ -156,9 +159,10 @@
 
     private final OwnAttributeResolver _attributeResolver = new OwnAttributeResolver(this);
 
-    @ManagedAttributeField( afterSet = "attainStateIfResolved" )
+    @ManagedAttributeField( afterSet = "attainStateIfOpenedOrReopenFailed" )
     private State _desiredState;
     private boolean _openComplete;
+    private boolean _openFailed;
     private volatile State _state = State.UNINITIALIZED;
 
     protected static Map<Class<? extends ConfiguredObject>, ConfiguredObject<?>> parentsMap(ConfiguredObject<?>... parents)
@@ -404,10 +408,19 @@
     {
         if(_dynamicState.compareAndSet(DynamicState.UNINIT, DynamicState.OPENED))
         {
-            doResolution(true);
-            doValidation(true);
-            doOpening(true);
-            doAttainState();
+            _openFailed = false;
+            OpenExceptionHandler exceptionHandler = new OpenExceptionHandler();
+            try
+            {
+                doResolution(true, exceptionHandler);
+                doValidation(true, exceptionHandler);
+                doOpening(true, exceptionHandler);
+                doAttainState(exceptionHandler);
+            }
+            catch(RuntimeException e)
+            {
+                exceptionHandler.handleException(e, this);
+            }
         }
     }
 
@@ -485,18 +498,76 @@
             _lastUpdatedTime = currentTime;
             _createdTime = currentTime;
 
-            doResolution(true);
-            doValidation(true);
+            CreateExceptionHandler createExceptionHandler = new CreateExceptionHandler();
+            try
+            {
+                doResolution(true, createExceptionHandler);
+                doValidation(true, createExceptionHandler);
+                validateOnCreate();
+                registerWithParents();
+            }
+            catch(RuntimeException e)
+            {
+                createExceptionHandler.handleException(e, this);
+            }
 
-            registerWithParents();
-
-            doCreation(true);
-            doOpening(true);
-            doAttainState();
+            AbstractConfiguredObjectExceptionHandler unregisteringExceptionHandler = new CreateExceptionHandler(true);
+            try
+            {
+                doCreation(true, unregisteringExceptionHandler);
+                doOpening(true, unregisteringExceptionHandler);
+                doAttainState(unregisteringExceptionHandler);
+            }
+            catch(RuntimeException e)
+            {
+                unregisteringExceptionHandler.handleException(e, this);
+            }
         }
     }
 
-    private void doAttainState()
+    protected void validateOnCreate()
+    {
+    }
+
+    protected final void handleExceptionOnOpen(RuntimeException e)
+    {
+        if (e instanceof ServerScopedRuntimeException)
+        {
+            throw e;
+        }
+
+        LOGGER.error("Failed to open object with name '" + getName() + "'.  Object will be put into ERROR state.", e);
+
+        try
+        {
+            onExceptionInOpen(e);
+        }
+        catch (RuntimeException re)
+        {
+            LOGGER.error("Unexpected exception while handling exception on open for " + getName(), e);
+        }
+
+        if (!_openComplete)
+        {
+            _openFailed = true;
+            _dynamicState.compareAndSet(DynamicState.OPENED, DynamicState.UNINIT);
+        }
+
+        //TODO: children of ERRORED CO will continue to remain in ACTIVE state
+        setState(State.ERRORED);
+    }
+
+    /**
+     * Callback method to perform ConfiguredObject specific exception handling on exception in open.
+     * <p/>
+     * The method is not expected to throw any runtime exception.
+     * @param e open exception
+     */
+    protected void onExceptionInOpen(RuntimeException e)
+    {
+    }
+
+    private void doAttainState(final AbstractConfiguredObjectExceptionHandler exceptionHandler)
     {
         applyToChildren(new Action<ConfiguredObject<?>>()
         {
@@ -505,14 +576,25 @@
             {
                 if (child instanceof AbstractConfiguredObject)
                 {
-                    ((AbstractConfiguredObject) child).doAttainState();
+                    AbstractConfiguredObject configuredObject = (AbstractConfiguredObject) child;
+                    if (configuredObject._dynamicState.get() == DynamicState.OPENED)
+                    {
+                        try
+                        {
+                            configuredObject.doAttainState(exceptionHandler);
+                        }
+                        catch (RuntimeException e)
+                        {
+                            exceptionHandler.handleException(e, configuredObject);
+                        }
+                    }
                 }
             }
         });
         attainState();
     }
 
-    protected void doOpening(final boolean skipCheck)
+    protected void doOpening(boolean skipCheck, final AbstractConfiguredObjectExceptionHandler exceptionHandler)
     {
         if(skipCheck || _dynamicState.compareAndSet(DynamicState.UNINIT,DynamicState.OPENED))
         {
@@ -523,9 +605,17 @@
                 @Override
                 public void performAction(final ConfiguredObject<?> child)
                 {
-                    if (child instanceof AbstractConfiguredObject)
+                    if (child.getState() != State.ERRORED && child instanceof AbstractConfiguredObject)
                     {
-                        ((AbstractConfiguredObject) child).doOpening(false);
+                        AbstractConfiguredObject configuredObject = (AbstractConfiguredObject) child;
+                        try
+                        {
+                            configuredObject.doOpening(false, exceptionHandler);
+                        }
+                        catch (RuntimeException e)
+                        {
+                            exceptionHandler.handleException(e, configuredObject);
+                        }
                     }
                 }
             });
@@ -533,7 +623,7 @@
         }
     }
 
-    protected final void doValidation(final boolean skipCheck)
+    protected final void doValidation(final boolean skipCheck, final AbstractConfiguredObjectExceptionHandler exceptionHandler)
     {
         if(skipCheck || _dynamicState.get() != DynamicState.OPENED)
         {
@@ -542,9 +632,17 @@
                 @Override
                 public void performAction(final ConfiguredObject<?> child)
                 {
-                    if (child instanceof AbstractConfiguredObject)
+                    if (child.getState() != State.ERRORED && child instanceof AbstractConfiguredObject)
                     {
-                        ((AbstractConfiguredObject) child).doValidation(false);
+                        AbstractConfiguredObject configuredObject = (AbstractConfiguredObject) child;
+                        try
+                        {
+                            configuredObject.doValidation(false, exceptionHandler);
+                        }
+                        catch (RuntimeException e)
+                        {
+                            exceptionHandler.handleException(e, configuredObject);
+                        }
                     }
                 }
             });
@@ -552,20 +650,28 @@
         }
     }
 
-    protected final void doResolution(final boolean skipCheck)
+    protected final void doResolution(boolean skipCheck, final AbstractConfiguredObjectExceptionHandler exceptionHandler)
     {
         if(skipCheck || _dynamicState.get() != DynamicState.OPENED)
         {
             onResolve();
             postResolve();
-            applyToChildren(new Action<ConfiguredObject<?>>()
+            applyToChildren(new Action()
             {
                 @Override
-                public void performAction(final ConfiguredObject<?> child)
+                public void performAction(Object child)
                 {
                     if (child instanceof AbstractConfiguredObject)
                     {
-                        ((AbstractConfiguredObject) child).doResolution(false);
+                        AbstractConfiguredObject configuredObject = (AbstractConfiguredObject) child;
+                        try
+                        {
+                            configuredObject.doResolution(false, exceptionHandler);
+                        }
+                        catch (RuntimeException e)
+                        {
+                            exceptionHandler.handleException(e, configuredObject);
+                        }
                     }
                 }
             });
@@ -576,7 +682,7 @@
     {
     }
 
-    protected final void doCreation(final boolean skipCheck)
+    protected final void doCreation(final boolean skipCheck, final AbstractConfiguredObjectExceptionHandler exceptionHandler)
     {
         if(skipCheck || _dynamicState.get() != DynamicState.OPENED)
         {
@@ -588,7 +694,15 @@
                 {
                     if (child instanceof AbstractConfiguredObject)
                     {
-                        ((AbstractConfiguredObject) child).doCreation(false);
+                        AbstractConfiguredObject configuredObject =(AbstractConfiguredObject) child;
+                        try
+                        {
+                            configuredObject.doCreation(false, exceptionHandler);
+                        }
+                        catch (RuntimeException e)
+                        {
+                            exceptionHandler.handleException(e, configuredObject);
+                        }
                     }
                 }
             });
@@ -711,12 +825,16 @@
         }
     }
 
-    private void attainStateIfResolved()
+    private void attainStateIfOpenedOrReopenFailed()
     {
-        if(_openComplete)
+        if (_openComplete || getDesiredState() == State.DELETED)
         {
             attainState();
         }
+        else if (_openFailed)
+        {
+            open();
+        }
     }
 
     protected void onOpen()
@@ -830,8 +948,13 @@
                                 State state = getState();
                                 if(desiredState == getDesiredState() && desiredState != state)
                                 {
-                                    attainState();
-                                    return getState();
+                                    attainStateIfOpenedOrReopenFailed();
+                                    final State currentState = getState();
+                                    if (currentState != state)
+                                    {
+                                        notifyStateChanged(state, currentState);
+                                    }
+                                    return currentState;
                                 }
                                 else
                                 {
@@ -1217,7 +1340,6 @@
         {
             if (_childrenByName.get(categoryClass).containsKey(name))
             {
-                child.delete();
                 throw new DuplicateNameException(child);
             }
             _childrenByName.get(categoryClass).put(name, child);
@@ -1756,4 +1878,54 @@
             return _name;
         }
     }
+
+    interface AbstractConfiguredObjectExceptionHandler
+    {
+        void handleException(RuntimeException exception, AbstractConfiguredObject<?> source);
+    }
+
+    private static class OpenExceptionHandler implements AbstractConfiguredObjectExceptionHandler
+    {
+        @Override
+        public void handleException(RuntimeException exception, AbstractConfiguredObject<?> source)
+        {
+            source.handleExceptionOnOpen(exception);
+        }
+    }
+
+    private static class CreateExceptionHandler implements AbstractConfiguredObjectExceptionHandler
+    {
+        private final boolean _unregister;
+
+        private CreateExceptionHandler()
+        {
+            this(false);
+        }
+
+        private CreateExceptionHandler(boolean unregister)
+        {
+            _unregister = unregister;
+        }
+
+        @Override
+
+        public void handleException(RuntimeException exception, AbstractConfiguredObject<?> source)
+        {
+            try
+            {
+                if (source.getState() != State.DELETED)
+                {
+                    source.delete();
+                }
+            }
+            finally
+            {
+                if (_unregister)
+                {
+                    source.unregister(false);
+                }
+                throw exception;
+            }
+        }
+    }
 }
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java
index 19f6139..f8dac7c 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java
@@ -49,13 +49,15 @@
     private final EventLogger _eventLogger;
     private final LogRecorder _logRecorder;
     private final BrokerOptions _brokerOptions;
+    private final BrokerShutdownProvider _brokerShutdownProvider;
 
     private DurableConfigurationStore _configurationStore;
 
     public AbstractSystemConfig(final TaskExecutor taskExecutor,
                                 final EventLogger eventLogger,
                                 final LogRecorder logRecorder,
-                                final BrokerOptions brokerOptions)
+                                final BrokerOptions brokerOptions,
+                                final BrokerShutdownProvider brokerShutdownProvider)
     {
         super(parentsMap(),
               updateAttributes(brokerOptions.convertToSystemAttributes()),
@@ -64,6 +66,7 @@
         getTaskExecutor().start();
         _logRecorder = logRecorder;
         _brokerOptions = brokerOptions;
+        _brokerShutdownProvider = brokerShutdownProvider;
     }
 
     private static Map<String, Object> updateAttributes(Map<String, Object> attributes)
@@ -212,4 +215,9 @@
 
     }
 
+    @Override
+    public BrokerShutdownProvider getBrokerShutdownProvider()
+    {
+        return _brokerShutdownProvider;
+    }
 }
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerShutdownProvider.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerShutdownProvider.java
new file mode 100644
index 0000000..5c8ab3e
--- /dev/null
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerShutdownProvider.java
@@ -0,0 +1,26 @@
+/*
+ *
+ * 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.server.model;
+
+public interface BrokerShutdownProvider
+{
+    void shutdown();
+}
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/JsonSystemConfigImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/JsonSystemConfigImpl.java
index 1763aca..c9a828e 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/model/JsonSystemConfigImpl.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/JsonSystemConfigImpl.java
@@ -38,9 +38,10 @@
     public JsonSystemConfigImpl(final TaskExecutor taskExecutor,
                                 final EventLogger eventLogger,
                                 final LogRecorder logRecorder,
-                                final BrokerOptions brokerOptions)
+                                final BrokerOptions brokerOptions,
+                                final BrokerShutdownProvider brokerShutdownProvider)
     {
-        super(taskExecutor, eventLogger, logRecorder, brokerOptions);
+        super(taskExecutor, eventLogger, logRecorder, brokerOptions, brokerShutdownProvider);
     }
 
     public String getStorePath()
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/SystemConfig.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/SystemConfig.java
index 7943c32..ec06314 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/model/SystemConfig.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/SystemConfig.java
@@ -37,4 +37,6 @@
     LogRecorder getLogRecorder();
 
     DurableConfigurationStore getConfigurationStore();
+
+    BrokerShutdownProvider getBrokerShutdownProvider();
 }
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
index 92ac43e..109aaff 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
@@ -943,6 +943,28 @@
         _eventLogger = eventLogger;
     }
 
+    @Override
+    protected void onExceptionInOpen(RuntimeException e)
+    {
+        SystemConfig systemConfig = getParent(SystemConfig.class);
+        if (systemConfig != null)
+        {
+            BrokerShutdownProvider shutdownProvider = systemConfig.getBrokerShutdownProvider();
+            if (shutdownProvider != null)
+            {
+                shutdownProvider.shutdown();
+            }
+            else
+            {
+                throw new IllegalStateException("Shutdown provider is not found in system config");
+            }
+        }
+        else
+        {
+            throw new IllegalStateException("SystemConfig is not found among broker parents");
+        }
+    }
+
     public void registerMessageDelivered(long messageSize)
     {
         _messagesDelivered.registerEvent(1L);
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java
index c96f4c0..1b3d059 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java
@@ -114,22 +114,27 @@
             throw new IllegalArgumentException("Cannot change the path");
         }
     }
+
+    @Override
     protected void onOpen()
     {
         super.onOpen();
-        if(_groupDatabase == null)
+        FileGroupDatabase groupDatabase = new FileGroupDatabase();
+        try
         {
-            _groupDatabase = new FileGroupDatabase();
-            try
-            {
-                _groupDatabase.setGroupFile(getPath());
-            }
-            catch (IOException e)
-            {
-                setState(State.ERRORED);
-                LOGGER.warn(("Unable to open preferences file at " + _path));
-            }
+            groupDatabase.setGroupFile(getPath());
         }
+        catch(IOException | RuntimeException e)
+        {
+            if (e instanceof IllegalConfigurationException)
+            {
+                throw (IllegalConfigurationException) e;
+            }
+            throw new IllegalConfigurationException(String.format("Cannot load groups from '%s'", getPath()), e);
+        }
+
+        _groupDatabase = groupDatabase;
+
         Set<Principal> groups = getGroupPrincipals();
         Collection<Group> principals = new ArrayList<Group>(groups.size());
         for (Principal group : groups)
@@ -150,43 +155,47 @@
     protected void onCreate()
     {
         super.onCreate();
-        _groupDatabase = new FileGroupDatabase();
-
         File file = new File(_path);
         if (!file.exists())
         {
             File parent = file.getParentFile();
-            if (!parent.exists())
+            if (!parent.exists() && !file.getParentFile().mkdirs())
             {
-                parent.mkdirs();
+                throw new IllegalConfigurationException(String.format("Cannot create groups file at '%s'",_path));
             }
-            if (parent.exists())
+            try
             {
-                try
-                {
-                    file.createNewFile();
-                }
-                catch (IOException e)
-                {
-                    throw new IllegalConfigurationException("Cannot create group file");
-                }
+                file.createNewFile();
             }
-            else
+            catch (IOException e)
             {
-                throw new IllegalConfigurationException("Cannot create group file");
+                throw new IllegalConfigurationException(String.format("Cannot create groups file at '%s'", _path), e);
             }
         }
-        try
-        {
-            _groupDatabase.setGroupFile(getPath());
-        }
-        catch (IOException e)
-        {
-            setState(State.ERRORED);
-            LOGGER.warn(("Unable to open preferences file at " + _path));
-        }
+    }
 
+    @Override
+    protected void validateOnCreate()
+    {
+        super.validateOnCreate();
+        File groupsFile = new File(_path);
+        if (groupsFile.exists())
+        {
+            if (!groupsFile.canRead())
+            {
+                throw new IllegalConfigurationException(String.format("Cannot read groups file '%s'. Please check permissions.", _path));
+            }
 
+            FileGroupDatabase groupDatabase = new FileGroupDatabase();
+            try
+            {
+                groupDatabase.setGroupFile(_path);
+            }
+            catch (Exception e)
+            {
+                throw new IllegalConfigurationException(String.format("Cannot load groups from '%s'", _path), e);
+            }
+        }
     }
 
     @Override
@@ -205,6 +214,11 @@
 
             getSecurityManager().authoriseGroupOperation(Operation.CREATE, groupName);
 
+            if (getState() != State.ACTIVE)
+            {
+                throw new IllegalConfigurationException(String.format("Group provider '%s' is not activated. Cannot create a group.", getName()));
+            }
+
             _groupDatabase.createGroup(groupName);
 
             Map<String,Object> attrMap = new HashMap<String, Object>();
@@ -247,20 +261,22 @@
         return _broker.getSecurityManager();
     }
 
-    @StateTransition( currentState = { State.UNINITIALIZED, State.QUIESCED }, desiredState = State.ACTIVE )
+    @StateTransition( currentState = { State.UNINITIALIZED, State.QUIESCED, State.ERRORED }, desiredState = State.ACTIVE )
     private void activate()
     {
-        try
+        if (_groupDatabase != null)
         {
-            _groupDatabase.setGroupFile(getPath());
             setState(State.ACTIVE);
         }
-        catch(IOException | RuntimeException e)
+        else
         {
-            setState(State.ERRORED);
             if (_broker.isManagementMode())
             {
-                LOGGER.warn("Failed to activate group provider: " + getName(), e);
+                        LOGGER.warn("Failed to activate group provider: " + getName());
+            }
+            else
+            {
+                throw new IllegalConfigurationException(String.format("Cannot load groups from '%s'", getPath()));
             }
         }
     }
@@ -268,6 +284,7 @@
     @StateTransition( currentState = { State.QUIESCED, State.ACTIVE, State.ERRORED}, desiredState = State.DELETED )
     private void doDelete()
     {
+        close();
         File file = new File(getPath());
         if (file.exists())
         {
@@ -289,7 +306,7 @@
 
     public Set<Principal> getGroupPrincipalsForUser(String username)
     {
-        Set<String> groups = _groupDatabase.getGroupsForUser(username);
+        Set<String> groups = _groupDatabase == null ? Collections.<String>emptySet(): _groupDatabase.getGroupsForUser(username);
         if (groups.isEmpty())
         {
             return Collections.emptySet();
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderImpl.java
index f2be4fd..e3ded30 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderImpl.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderImpl.java
@@ -76,20 +76,64 @@
         _authenticationProvider = authenticationProvider;
     }
 
-    @StateTransition( currentState = State.UNINITIALIZED, desiredState = State.ACTIVE )
+    @Override
+    protected void validateOnCreate()
+    {
+        super.validateOnCreate();
+        File storeFile  = new File(_path);
+        if (storeFile.exists() )
+        {
+            if (!storeFile.canRead())
+            {
+                throw new IllegalConfigurationException(String.format("Cannot read preferences file '%s'. Please check permissions.", _path));
+            }
+
+            FileSystemPreferencesStore store = null;
+            try
+            {
+                store = new FileSystemPreferencesStore(storeFile);
+                store.open();
+            }
+            catch (RuntimeException e)
+            {
+                if (e instanceof IllegalConfigurationException)
+                {
+                    throw e;
+                }
+                throw new IllegalConfigurationException(String.format("Cannot open preferences store at '%s'", _path), e);
+            }
+            finally
+            {
+                if (store != null)
+                {
+                    store.close();
+                }
+            }
+        }
+    }
+
+    @Override
+    protected void onOpen()
+    {
+        FileSystemPreferencesStore store = new FileSystemPreferencesStore(new File(_path));
+
+        // we need to check and create file if it does not exist every time on open
+        store.createIfNotExist();
+        store.open();
+        _store = store;
+        _open = true;
+    }
+
+    @StateTransition( currentState = {State.UNINITIALIZED, State.ERRORED}, desiredState = State.ACTIVE )
     private void activate()
     {
-        try
+        if (_store != null)
         {
-            _store = new FileSystemPreferencesStore(new File(_path));
-            createStoreIfNotExist();
-            _store.open();
-            _open = true;
             setState(State.ACTIVE);
         }
-        catch( RuntimeException e )
+        else
         {
-            setState(State.ERRORED);
+            throw new IllegalStateException("Cannot open preferences provider " + getName() + " in state " + getState() );
         }
     }
 
@@ -148,9 +192,14 @@
         setState(State.DELETED);
     }
 
-    @StateTransition(currentState = { State.QUIESCED, State.ERRORED }, desiredState = State.ACTIVE )
+    @StateTransition(currentState = State.QUIESCED, desiredState = State.ACTIVE )
     private void restart()
     {
+        if (_store == null)
+        {
+            throw new IllegalStateException("Cannot open preferences provider " + getName() + " in state " + getState() );
+        }
+
         _store.open();
         setState(State.ACTIVE);
     }
@@ -158,24 +207,39 @@
     @Override
     public Map<String, Object> getPreferences(String userId)
     {
-        return _store.getPreferences(userId);
+        return _store == null? Collections.<String, Object>emptyMap() : _store.getPreferences(userId);
     }
 
     @Override
     public Map<String, Object> setPreferences(String userId, Map<String, Object> preferences)
     {
+        if (_store == null)
+        {
+            throw new IllegalStateException("Cannot set preferences with preferences provider " + getName() + " in state " + getState() );
+        }
+
         return _store.setPreferences(userId, preferences);
     }
 
     @Override
     public String[] deletePreferences(String... userIDs)
     {
+        if (_store == null)
+        {
+            throw new IllegalStateException("Cannot delete preferences with preferences provider " + getName() + " in state " + getState() );
+        }
+
         return _store.deletePreferences(userIDs);
     }
 
     @Override
     public Set<String> listUserIDs()
     {
+        if (_store == null)
+        {
+            return Collections.emptySet();
+        }
+
         return _store.listUserIDs();
     }
 
@@ -215,9 +279,10 @@
             }
             else
             {
-                _store = new FileSystemPreferencesStore(new File(_path));
-                createStoreIfNotExist();
-                _store.open();
+                FileSystemPreferencesStore store = new FileSystemPreferencesStore(new File(_path));
+                store.createIfNotExist();
+                store.open();
+                _store = store;
             }
         }
     }
@@ -265,11 +330,6 @@
 
     }
 
-    private void createStoreIfNotExist()
-    {
-        _store.createIfNotExist();
-    }
-
     public static class FileSystemPreferencesStore
     {
         private final ObjectMapper _objectMapper;
@@ -294,18 +354,18 @@
                 File parent = _storeFile.getParentFile();
                 if (!parent.exists() && !parent.mkdirs())
                 {
-                    throw new IllegalConfigurationException("Cannot create preferences store folders");
+                    throw new IllegalConfigurationException(String.format("Cannot create preferences store folder at '%s'", _storeFile.getAbsolutePath()));
                 }
                 try
                 {
                     if (_storeFile.createNewFile() && !_storeFile.exists())
                     {
-                        throw new IllegalConfigurationException("Preferences store file was not created:" + _storeFile.getAbsolutePath());
+                        throw new IllegalConfigurationException(String.format("Cannot create preferences store file at '%s'", _storeFile.getAbsolutePath()));
                     }
                 }
                 catch (IOException e)
                 {
-                    throw new IllegalConfigurationException("Cannot create preferences store file");
+                    throw new IllegalConfigurationException(String.format("Cannot create preferences store file at '%s'", _storeFile.getAbsolutePath()), e);
                 }
             }
         }
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java
index c0aa99a..e2e7eff 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java
@@ -317,7 +317,7 @@
         setState(State.DELETED);
     }
 
-    @StateTransition( currentState = {State.UNINITIALIZED, State.QUIESCED}, desiredState = State.ACTIVE )
+    @StateTransition( currentState = {State.UNINITIALIZED, State.QUIESCED, State.ERRORED}, desiredState = State.ACTIVE )
     protected void activate()
     {
         try
@@ -327,8 +327,7 @@
         catch (RuntimeException e)
         {
             setState(State.ERRORED);
-            LOGGER.error("Unable to active port '" + getName() + "'of type " + getType() + " on port " + getPort(),
-                         e);
+            throw new IllegalConfigurationException("Unable to active port '" + getName() + "'of type " + getType() + " on " + getPort(), e);
         }
     }
 
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java
index fe7d419..afe3c9a 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java
@@ -34,6 +34,7 @@
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.X509TrustManager;
 
+import org.apache.qpid.server.util.PortUtil;
 import org.codehaus.jackson.map.ObjectMapper;
 
 import org.apache.qpid.server.configuration.BrokerProperties;
@@ -187,6 +188,18 @@
         }
     }
 
+    @Override
+    public void validateOnCreate()
+    {
+        super.validateOnCreate();
+        String bindingAddress = getBindingAddress();
+        if (!PortUtil.isPortAvailable(bindingAddress, getPort()))
+        {
+            throw new IllegalConfigurationException(String.format("Cannot bind to port %d and binding address '%s'. Port is already is use.",
+                    getPort(), bindingAddress == null || "".equals(bindingAddress) ? "*" : bindingAddress));
+        }
+    }
+
     private SSLContext createSslContext()
     {
         KeyStore keyStore = getKeyStore();
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPortImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPortImpl.java
index 1774f16..3be5854 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPortImpl.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPortImpl.java
@@ -22,10 +22,12 @@
 
 import java.util.Map;
 
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
 import org.apache.qpid.server.model.Broker;
 import org.apache.qpid.server.model.ManagedAttributeField;
 import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
 import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.util.PortUtil;
 
 public class HttpPortImpl extends AbstractClientAuthCapablePortWithAuthProvider<HttpPortImpl> implements HttpPort<HttpPortImpl>
 {
@@ -65,4 +67,16 @@
             return State.QUIESCED;
         }
     }
+
+    @Override
+    public void validateOnCreate()
+    {
+        super.validateOnCreate();
+        String bindingAddress = getBindingAddress();
+        if (!PortUtil.isPortAvailable(bindingAddress, getPort()))
+        {
+            throw new IllegalConfigurationException(String.format("Cannot bind to port %d and binding address '%s'. Port is already is use.",
+                    getPort(), bindingAddress == null || "".equals(bindingAddress) ? "*" : bindingAddress));
+        }
+    }
 }
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemConfigFactory.java b/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemConfigFactory.java
index 9162f9e..885194d 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemConfigFactory.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemConfigFactory.java
@@ -24,6 +24,7 @@
 import org.apache.qpid.server.configuration.updater.TaskExecutor;
 import org.apache.qpid.server.logging.EventLogger;
 import org.apache.qpid.server.logging.LogRecorder;
+import org.apache.qpid.server.model.BrokerShutdownProvider;
 import org.apache.qpid.server.model.SystemConfig;
 
 public interface SystemConfigFactory<X extends SystemConfig<X>> extends Pluggable
@@ -31,5 +32,6 @@
     public X newInstance(final TaskExecutor taskExecutor,
                          final EventLogger eventLogger,
                          final LogRecorder logRecorder,
-                         final BrokerOptions brokerOptions);
+                         final BrokerOptions brokerOptions,
+                         final BrokerShutdownProvider brokerShutdownProvider);
 }
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java b/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java
index a5156c9..53e446b 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java
@@ -254,6 +254,12 @@
     }
 
     @Override
+    protected void validateOnCreate()
+    {
+        _virtualHost.getSecurityManager().authoriseCreateQueue(this);
+    }
+
+    @Override
     protected void onCreate()
     {
         super.onCreate();
@@ -304,6 +310,7 @@
         }
     }
 
+    @Override
     protected void onOpen()
     {
         super.onOpen();
@@ -319,17 +326,6 @@
 
         _logSubject = new QueueLogSubject(this);
 
-        try
-        {
-
-            _virtualHost.getSecurityManager().authoriseCreateQueue(this);
-        }
-        catch(AccessControlException e)
-        {
-            deleted();
-            throw e;
-        }
-
         Subject activeSubject = Subject.getSubject(AccessController.getContext());
         Set<SessionPrincipal> sessionPrincipals = activeSubject == null ? Collections.<SessionPrincipal>emptySet() : activeSubject.getPrincipals(SessionPrincipal.class);
         AMQSessionModel<?,?> sessionModel;
@@ -2798,7 +2794,7 @@
 
     //=============
 
-    @StateTransition(currentState = State.UNINITIALIZED, desiredState = State.ACTIVE)
+    @StateTransition(currentState = {State.UNINITIALIZED,State.ERRORED}, desiredState = State.ACTIVE)
     private void activate()
     {
         setState(State.ACTIVE);
@@ -2965,7 +2961,10 @@
         {
             throw new IllegalConfigurationException("Flow resume size can't be greater than flow control size");
         }
-
+        else if (changedAttributes.contains(DURABLE) && proxyForValidation.isDurable() != isDurable())
+        {
+            throw new IllegalConfigurationException("Message durability cannot be modified after queue creation");
+        }
 
         for (String attrName : NON_NEGATIVE_NUMBERS)
         {
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
index a6a2ea8..192a096 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
@@ -76,25 +76,32 @@
     }
 
     @Override
+    protected void validateOnCreate()
+    {
+        super.validateOnCreate();
+        File passwordFile = new File(_path);
+        if (passwordFile.exists() && !passwordFile.canRead())
+        {
+            throw new IllegalConfigurationException(String.format("Cannot read password file '%s'. Please check permissions.", _path));
+        }
+    }
+
+    @Override
     protected void onCreate()
     {
         super.onCreate();
-        try
+        File passwordFile = new File(_path);
+        if (!passwordFile.exists())
         {
-            File passwordFile = new File(_path);
-            if (!passwordFile.exists())
+            try
             {
                 passwordFile.createNewFile();
             }
-            else if (!passwordFile.canRead())
+            catch (IOException e)
             {
-                throw new IllegalConfigurationException("Cannot read password file" + _path + ". Check permissions.");
+                throw new IllegalConfigurationException(String.format("Cannot create password file at '%s'", _path), e);
             }
         }
-        catch (IOException e)
-        {
-            throw new IllegalConfigurationException("Cannot use password database at :" + _path, e);
-        }
     }
 
     @Override
@@ -102,23 +109,14 @@
     {
         super.onOpen();
         _principalDatabase = createDatabase();
-        try
+        initialise();
+        List<Principal> users = _principalDatabase == null ? Collections.<Principal>emptyList() : _principalDatabase.getUsers();
+        for (Principal user : users)
         {
-            initialise();
-            List<Principal> users =
-                    _principalDatabase == null ? Collections.<Principal>emptyList() : _principalDatabase.getUsers();
-            for (Principal user : users)
-            {
-                PrincipalAdapter principalAdapter = new PrincipalAdapter(user);
-                principalAdapter.registerWithParents();
-                principalAdapter.open();
-                _userMap.put(user, principalAdapter);
-            }
-        }
-        catch(IllegalConfigurationException e)
-        {
-            setState(State.ERRORED);
-
+            PrincipalAdapter principalAdapter = new PrincipalAdapter(user);
+            principalAdapter.registerWithParents();
+            principalAdapter.open();
+            _userMap.put(user, principalAdapter);
         }
     }
 
@@ -457,7 +455,7 @@
             return super.changeAttribute(name, expected, desired);
         }
 
-        @StateTransition(currentState = State.UNINITIALIZED, desiredState = State.ACTIVE)
+        @StateTransition(currentState = {State.UNINITIALIZED,State.ERRORED}, desiredState = State.ACTIVE)
         private void activate()
         {
             setState(State.ACTIVE);
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java
index 4e285df..260fdfd 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java
@@ -22,6 +22,7 @@
 
 import org.apache.qpid.server.model.AuthenticationProvider;
 import org.apache.qpid.server.model.ManagedAttribute;
+import org.apache.qpid.server.model.ManagedContextDefault;
 import org.apache.qpid.server.model.ManagedObject;
 import org.apache.qpid.server.model.TrustStore;
 
@@ -29,24 +30,34 @@
 public interface SimpleLDAPAuthenticationManager<X extends SimpleLDAPAuthenticationManager<X>> extends AuthenticationProvider<X>
 {
     String PROVIDER_TYPE = "SimpleLDAP";
+    String PROVIDER_URL = "providerUrl";
+    String PROVIDER_AUTH_URL = "providerAuthUrl";
+    String SEARCH_CONTEXT = "searchContext";
+    String LDAP_CONTEXT_FACTORY = "ldapContextFactory";
+    String SEARCH_USERNAME = "getSearchUsername";
+    String SEARCH_PASSWORD = "getSearchPassword";
     String TRUST_STORE = "trustStore";
 
-    @ManagedAttribute( description = "LDAP server URL" )
+
+    @ManagedAttribute( description = "LDAP server URL", mandatory = true)
     String getProviderUrl();
 
     @ManagedAttribute( description = "LDAP authentication URL")
     String getProviderAuthUrl();
 
-    @ManagedAttribute( description = "Search context")
+    @ManagedAttribute( description = "Search context", mandatory = true)
     String getSearchContext();
 
-    @ManagedAttribute( description = "Search filter")
+    @ManagedAttribute( description = "Search filter", mandatory = true)
     String getSearchFilter();
 
     @ManagedAttribute( description = "Bind without search")
     boolean isBindWithoutSearch();
 
-    @ManagedAttribute( description = "LDAP context factory")
+    @ManagedContextDefault( name = "ldap.context.factory")
+    String DEFAULT_LDAP_CONTEXT_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";
+
+    @ManagedAttribute( description = "LDAP context factory", defaultValue = "${ldap.context.factory}")
     String getLdapContextFactory();
 
     @ManagedAttribute( description = "Trust store name")
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerImpl.java
index a0ba451..6a0b83e 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerImpl.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerImpl.java
@@ -19,15 +19,18 @@
 
 package org.apache.qpid.server.security.auth.manager;
 
+import static java.util.Collections.disjoint;
+import static java.util.Collections.unmodifiableList;
+import static java.util.Collections.singletonList;
+
 import java.io.IOException;
 import java.security.GeneralSecurityException;
-import java.security.KeyManagementException;
-import java.security.NoSuchAlgorithmException;
 import java.security.Principal;
-import java.util.Collections;
+import java.util.Arrays;
 import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import javax.naming.AuthenticationException;
 import javax.naming.Context;
@@ -48,7 +51,9 @@
 
 import org.apache.log4j.Logger;
 
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
 import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.ConfiguredObject;
 import org.apache.qpid.server.model.ManagedAttributeField;
 import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
 import org.apache.qpid.server.model.TrustStore;
@@ -59,7 +64,6 @@
 import org.apache.qpid.server.security.auth.manager.ldap.LDAPSSLSocketFactoryGenerator;
 import org.apache.qpid.server.security.auth.sasl.plain.PlainPasswordCallback;
 import org.apache.qpid.server.security.auth.sasl.plain.PlainSaslServer;
-import org.apache.qpid.server.util.ServerScopedRuntimeException;
 import org.apache.qpid.server.util.StringUtil;
 import org.apache.qpid.ssl.SSLContextFactory;
 
@@ -68,6 +72,14 @@
 {
     private static final Logger _logger = Logger.getLogger(SimpleLDAPAuthenticationManagerImpl.class);
 
+    private static final List<String> CONNECTIVITY_ATTRS = unmodifiableList(Arrays.asList(PROVIDER_URL,
+                                                                             PROVIDER_AUTH_URL,
+                                                                             SEARCH_CONTEXT,
+                                                                             LDAP_CONTEXT_FACTORY,
+                                                                             SEARCH_USERNAME,
+                                                                             SEARCH_PASSWORD,
+                                                                             TRUST_STORE));
+
     /**
      * Environment key to instruct {@link InitialDirContext} to override the socket factory.
      */
@@ -111,15 +123,37 @@
         super(attributes, broker);
     }
 
+    @Override
+    protected void validateOnCreate()
+    {
+        super.validateOnCreate();
+
+        Class<? extends SocketFactory> sslSocketFactoryOverrideClass = _trustStore == null ? null : createSslSocketFactoryOverrideClass(_trustStore);
+        validateInitialDirContext(sslSocketFactoryOverrideClass, _providerUrl, _searchUsername, _searchPassword);
+    }
+
+    @Override
+    protected void validateChange(final ConfiguredObject<?> proxyForValidation, final Set<String> changedAttributes)
+    {
+        super.validateChange(proxyForValidation, changedAttributes);
+
+        if (!disjoint(changedAttributes, CONNECTIVITY_ATTRS))
+        {
+            SimpleLDAPAuthenticationManager changed = (SimpleLDAPAuthenticationManager)proxyForValidation;
+            TrustStore changedTruststore = changed.getTrustStore();
+            Class<? extends SocketFactory> sslSocketFactoryOverrideClass = changedTruststore == null ? null : createSslSocketFactoryOverrideClass(
+                    changedTruststore);
+            validateInitialDirContext(sslSocketFactoryOverrideClass, changed.getProviderUrl(), changed.getSearchUsername(),
+                                      changed.getSearchPassword());
+        }
+    }
 
     @Override
     protected void onOpen()
     {
         super.onOpen();
 
-        _sslSocketFactoryOverrideClass = createSslSocketFactoryOverrideClass();
-
-      //  validateInitialDirContext();
+        _sslSocketFactoryOverrideClass = _trustStore == null ? null : createSslSocketFactoryOverrideClass(_trustStore);
     }
 
     @Override
@@ -174,7 +208,7 @@
     @Override
     public List<String> getMechanisms()
     {
-        return Collections.singletonList(PlainSaslServer.MECHANISM);
+        return singletonList(PlainSaslServer.MECHANISM);
     }
 
     @Override
@@ -259,7 +293,7 @@
         InitialDirContext ctx = null;
         try
         {
-            ctx = createInitialDirContext(env);
+            ctx = createInitialDirContext(env, _sslSocketFactoryOverrideClass);
 
             //Authentication succeeded
             return new AuthenticationResult(new UsernamePrincipal(name));
@@ -291,7 +325,8 @@
         return env;
     }
 
-    private InitialDirContext createInitialDirContext(Hashtable<String, Object> env) throws NamingException
+    private InitialDirContext createInitialDirContext(Hashtable<String, Object> env,
+                                                      Class<? extends SocketFactory> sslSocketFactoryOverrideClass) throws NamingException
     {
         ClassLoader existingContextClassLoader = null;
 
@@ -300,11 +335,11 @@
         boolean revertContentClassLoader = false;
         try
         {
-            if (isLdaps && _sslSocketFactoryOverrideClass != null)
+            if (isLdaps && sslSocketFactoryOverrideClass != null)
             {
                 existingContextClassLoader = Thread.currentThread().getContextClassLoader();
-                env.put(JAVA_NAMING_LDAP_FACTORY_SOCKET, _sslSocketFactoryOverrideClass.getName());
-                Thread.currentThread().setContextClassLoader(_sslSocketFactoryOverrideClass.getClassLoader());
+                env.put(JAVA_NAMING_LDAP_FACTORY_SOCKET, sslSocketFactoryOverrideClass.getName());
+                Thread.currentThread().setContextClassLoader(sslSocketFactoryOverrideClass.getClassLoader());
                 revertContentClassLoader = true;
             }
             return new InitialDirContext(env);
@@ -323,59 +358,59 @@
      * associated with the {@link SSLContext} generated from that trust store.
      *
      * @return generated socket factory class
+     * @param trustStore
      */
-    private Class<? extends SocketFactory> createSslSocketFactoryOverrideClass()
+    private Class<? extends SocketFactory> createSslSocketFactoryOverrideClass(final TrustStore trustStore)
     {
-        if (_trustStore != null)
+        String clazzName = new StringUtil().createUniqueJavaName(getName() + "_" + trustStore.getName());
+        SSLContext sslContext = null;
+        try
         {
-            String clazzName = new StringUtil().createUniqueJavaName(getName());
-            SSLContext sslContext = null;
-            try
-            {
-                sslContext = SSLContext.getInstance("TLS");
-                sslContext.init(null, _trustStore.getTrustManagers(), null);
-            }
-            catch (NoSuchAlgorithmException e)
-            {
-                _logger.error("Exception creating SSLContext", e);
-                throw new ServerScopedRuntimeException("Error creating SSLContext for trust store : " + _trustStore.getName() , e);
-            }
-            catch (KeyManagementException e)
-            {
-                _logger.error("Exception creating SSLContext", e);
-                throw new ServerScopedRuntimeException("Error creating SSLContext for trust store : " + _trustStore.getName() , e);
-            }
-            catch (GeneralSecurityException e)
-            {
-                _logger.error("Exception creating SSLContext", e);
-                throw new ServerScopedRuntimeException("Error creating SSLContext for trust store : " + _trustStore.getName() , e);
-            }
-
-            Class<? extends AbstractLDAPSSLSocketFactory> clazz = LDAPSSLSocketFactoryGenerator.createSubClass(clazzName, sslContext.getSocketFactory());
-            if (_logger.isDebugEnabled())
-            {
-                _logger.debug("Connection to Directory will use custom SSL socket factory : " +  clazz);
-            }
-            return clazz;
+            sslContext = SSLContext.getInstance("TLS");
+            sslContext.init(null, trustStore.getTrustManagers(), null);
+        }
+        catch (GeneralSecurityException e)
+        {
+            _logger.error("Exception creating SSLContext", e);
+            throw new IllegalConfigurationException("Error creating SSLContext with trust store : " + trustStore.getName() , e);
         }
 
-        return null;
+        Class<? extends AbstractLDAPSSLSocketFactory> clazz = LDAPSSLSocketFactoryGenerator.createSubClass(clazzName, sslContext.getSocketFactory());
+        if (_logger.isDebugEnabled())
+        {
+            _logger.debug("Connection to Directory will use custom SSL socket factory : " +  clazz);
+        }
+        return clazz;
     }
 
-    private void validateInitialDirContext()
+    @Override
+    public String toString()
     {
-        Hashtable<String,Object> env = createInitialDirContextEnvironment(_providerUrl);
+        return "SimpleLDAPAuthenticationManagerImpl [id=" + getId() + ", name=" + getName() +
+               ", providerUrl=" + _providerUrl + ", providerAuthUrl=" + _providerAuthUrl +
+               ", searchContext=" + _searchContext + ", state=" + getState() +
+               ", searchFilter=" + _searchFilter + ", ldapContextFactory=" + _ldapContextFactory +
+               ", bindWithoutSearch=" + _bindWithoutSearch  + ", trustStore=" + _trustStore  +
+               ", searchUsername=" + _searchUsername + "]";
+    }
 
-        setupSearchContext(env);
+    private void validateInitialDirContext(Class<? extends SocketFactory> sslSocketFactoryOverrideClass,
+                                           final String providerUrl,
+                                           final String searchUsername, final String searchPassword)
+    {
+        Hashtable<String,Object> env = createInitialDirContextEnvironment(providerUrl);
+
+        setupSearchContext(env, searchUsername, searchPassword);
 
         InitialDirContext ctx = null;
         try
         {
-            ctx = createInitialDirContext(env);
+            ctx = createInitialDirContext(env, sslSocketFactoryOverrideClass);
         }
         catch (NamingException e)
         {
-            throw new ServerScopedRuntimeException("Unable to establish connection to the ldap server at " + _providerUrl, e);
+            _logger.error("Failed to establish connectivity to the ldap server for " + providerUrl, e);
+            throw new IllegalConfigurationException("Failed to establish connectivity to the ldap server." , e);
         }
         finally
         {
@@ -383,13 +418,14 @@
         }
     }
 
-    private void setupSearchContext(final Hashtable<String, Object> env)
+    private void setupSearchContext(final Hashtable<String, Object> env,
+                                    final String searchUsername, final String searchPassword)
     {
         if(_searchUsername != null && _searchUsername.trim().length()>0)
         {
             env.put(Context.SECURITY_AUTHENTICATION, "simple");
-            env.put(Context.SECURITY_PRINCIPAL, _searchUsername);
-            env.put(Context.SECURITY_CREDENTIALS, _searchPassword);
+            env.put(Context.SECURITY_PRINCIPAL, searchUsername);
+            env.put(Context.SECURITY_CREDENTIALS, searchPassword);
         }
         else
         {
@@ -454,9 +490,9 @@
         {
             Hashtable<String, Object> env = createInitialDirContextEnvironment(_providerUrl);
 
-            setupSearchContext(env);
+            setupSearchContext(env, _searchUsername, _searchPassword);
 
-            InitialDirContext ctx = createInitialDirContext(env);
+            InitialDirContext ctx = createInitialDirContext(env, _sslSocketFactoryOverrideClass);
 
             try
             {
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCConfigurationStore.java b/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCConfigurationStore.java
index 5207267..4fbfdfd 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCConfigurationStore.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCConfigurationStore.java
@@ -572,7 +572,7 @@
         }
         catch (SQLException e)
         {
-            throw new StoreException("Error creating ConfiguredObject " + object);
+            throw new StoreException("Error creating ConfiguredObject " + object, e);
         }
     }
 
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java b/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java
index 9633e32..4dfaa71 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java
@@ -133,7 +133,7 @@
         }
         catch (SQLException e)
         {
-            throw new StoreException(e);
+            throw new StoreException("Failed to determine maximum ids", e);
         }
 
     }
@@ -816,7 +816,6 @@
 
     private void commitTran(ConnectionWrapper connWrapper) throws StoreException
     {
-
         try
         {
             Connection conn = connWrapper.getConnection();
@@ -833,10 +832,6 @@
         {
             throw new StoreException("Error commit tx: " + e.getMessage(), e);
         }
-        finally
-        {
-
-        }
     }
 
     private StoreFuture commitTranAsync(ConnectionWrapper connWrapper) throws StoreException
@@ -1448,7 +1443,7 @@
                 }
                 catch (SQLException e)
                 {
-                    throw new StoreException(e);
+                    throw new StoreException("Failed to get metadata for message id: " + _messageId, e);
                 }
             }
 
@@ -1507,7 +1502,7 @@
                         }
                         catch (SQLException e)
                         {
-                            throw new StoreException(e);
+                            throw new StoreException("Failed to get content for message id " + _messageId, e);
                         }
                     }
                     else
@@ -1551,7 +1546,7 @@
                         }
                         catch (SQLException e)
                         {
-                            throw new StoreException(e);
+                            throw new StoreException("Failed to get content for message id: " + _messageId, e);
                         }
                     }
                     else
@@ -1598,11 +1593,7 @@
             }
             catch (SQLException e)
             {
-                throw new StoreException(e);
-            }
-            finally
-            {
-
+                throw new StoreException("Failed to flow to disk", e);
             }
             return true;
         }
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/util/PortUtil.java b/java/broker-core/src/main/java/org/apache/qpid/server/util/PortUtil.java
new file mode 100644
index 0000000..5d093bd
--- /dev/null
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/util/PortUtil.java
@@ -0,0 +1,69 @@
+/*
+ *
+ * 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.server.util;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+
+public class PortUtil
+{
+    public static boolean isPortAvailable(String hostName, int port)
+    {
+        InetSocketAddress socketAddress = null;
+        if ( hostName == null || "".equals(hostName) || "*".equals(hostName) )
+        {
+            socketAddress = new InetSocketAddress(port);
+        }
+        else
+        {
+            socketAddress = new InetSocketAddress(hostName, port);
+        }
+
+        ServerSocket serverSocket = null;
+        try
+        {
+            serverSocket = new ServerSocket();
+            serverSocket.setReuseAddress(true);
+            serverSocket.bind(socketAddress);
+            return true;
+        }
+        catch (IOException e)
+        {
+            return false;
+        }
+        finally
+        {
+            if (serverSocket != null)
+            {
+                try
+                {
+                    serverSocket.close();
+                }
+                catch (IOException e)
+                {
+                    throw new RuntimeException("Couldn't close port " + port + " that was created to check its availability", e);
+                }
+            }
+        }
+    }
+}
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java
index f52c196..48077ba 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java
@@ -37,7 +37,6 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.AtomicReference;
 
 import javax.security.auth.Subject;
 
@@ -231,6 +230,47 @@
     }
 
     @Override
+    public void validateOnCreate()
+    {
+        super.validateOnCreate();
+        validateMessageStoreCreation();
+    }
+
+    private void validateMessageStoreCreation()
+    {
+        MessageStore store = createMessageStore();
+        if (store != null)
+        {
+            try
+            {
+                store.openMessageStore(this);
+            }
+            catch (Exception e)
+            {
+                throw new IllegalConfigurationException("Cannot open virtual host message store:" + e.getMessage(), e);
+            }
+            finally
+            {
+                try
+                {
+                    store.closeMessageStore();
+                }
+                catch(Exception e)
+                {
+                    _logger.warn("Failed to close database", e);
+                }
+            }
+        }
+    }
+
+    @Override
+    protected void onExceptionInOpen(RuntimeException e)
+    {
+        super.onExceptionInOpen(e);
+        closeMessageStore();
+    }
+
+    @Override
     protected void onOpen()
     {
         super.onOpen();
@@ -638,6 +678,7 @@
 
     protected void onClose()
     {
+        setState(State.UNAVAILABLE);
         //Stop Connections
         _connectionRegistry.close();
         _dtxRegistry.close();
@@ -659,11 +700,11 @@
             {
                 _logger.error("Failed to close message store", e);
             }
-        }
 
-        if (!(_virtualHostNode.getConfigurationStore() instanceof MessageStoreProvider))
-        {
-            getEventLogger().message(getMessageStoreLogSubject(), MessageStoreMessages.CLOSED());
+            if (!(_virtualHostNode.getConfigurationStore() instanceof MessageStoreProvider))
+            {
+                getEventLogger().message(getMessageStoreLogSubject(), MessageStoreMessages.CLOSED());
+            }
         }
     }
 
@@ -1355,7 +1396,7 @@
         getDurableConfigurationStore().create(new ConfiguredObjectRecordImpl(record.getId(), record.getType(), record.getAttributes()));
     }
 
-    @StateTransition( currentState = { State.UNINITIALIZED }, desiredState = State.ACTIVE )
+    @StateTransition( currentState = { State.UNINITIALIZED,State.ERRORED }, desiredState = State.ACTIVE )
     private void onActivate()
     {
         _houseKeepingTasks = new ScheduledThreadPoolExecutor(getHousekeepingThreadCount());
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java
index ce97502..03c30a9 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java
@@ -41,6 +41,7 @@
 import org.apache.qpid.server.security.SecurityManager;
 import org.apache.qpid.server.store.ConfiguredObjectRecord;
 import org.apache.qpid.server.store.ConfiguredObjectRecordImpl;
+import org.apache.qpid.server.store.DurableConfigurationStore;
 import org.apache.qpid.server.store.VirtualHostStoreUpgraderAndRecoverer;
 
 public abstract class AbstractStandardVirtualHostNode<X extends AbstractStandardVirtualHostNode<X>> extends AbstractVirtualHostNode<X>
@@ -169,4 +170,33 @@
     {
         return Collections.emptyList();
     }
+
+    @Override
+    public void validateOnCreate()
+    {
+        super.validateOnCreate();
+        DurableConfigurationStore store = createConfigurationStore();
+        if (store != null)
+        {
+            try
+            {
+                store.openConfigurationStore(this, false);
+            }
+            catch (Exception e)
+            {
+                throw new IllegalConfigurationException("Cannot open node configuration store:" + e.getMessage(), e);
+            }
+            finally
+            {
+                try
+                {
+                    store.closeConfigurationStore();
+                }
+                catch(Exception e)
+                {
+                    LOGGER.warn("Failed to close database", e);
+                }
+            }
+        }
+    }
 }
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java
index 5cbfb09..aea07e3 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java
@@ -36,7 +36,6 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
-import java.util.concurrent.atomic.AtomicReference;
 
 import org.apache.log4j.Logger;
 
@@ -100,8 +99,6 @@
     {
         super.onOpen();
         _durableConfigurationStore = createConfigurationStore();
-        _configurationStoreLogSubject = new MessageStoreLogSubject(getName(), _durableConfigurationStore.getClass().getSimpleName());
-
     }
 
     @Override
@@ -167,11 +164,6 @@
         return _eventLogger;
     }
 
-    protected DurableConfigurationStore getDurableConfigurationStore()
-    {
-        return _durableConfigurationStore;
-    }
-
     protected MessageStoreLogSubject getConfigurationStoreLogSubject()
     {
         return _configurationStoreLogSubject;
@@ -184,7 +176,11 @@
         deleteVirtualHostIfExists();
         close();
         deleted();
-        getConfigurationStore().onDelete(this);
+        DurableConfigurationStore configurationStore = getConfigurationStore();
+        if (configurationStore != null)
+        {
+            configurationStore.onDelete(this);
+        }
     }
 
     protected void deleteVirtualHostIfExists()
@@ -205,11 +201,30 @@
     protected void stopAndSetStateTo(State stoppedState)
     {
         closeChildren();
-        closeConfigurationStore();
+        closeConfigurationStoreSafely();
         setState(stoppedState);
     }
 
     @Override
+    protected void onExceptionInOpen(RuntimeException e)
+    {
+        super.onExceptionInOpen(e);
+        closeConfigurationStoreSafely();
+    }
+
+    @Override
+    protected void postResolve()
+    {
+        super.postResolve();
+        DurableConfigurationStore store = getConfigurationStore();
+        if (store == null)
+        {
+            store = createConfigurationStore();
+        }
+        _configurationStoreLogSubject = new MessageStoreLogSubject(getName(), store.getClass().getSimpleName());
+    }
+
+    @Override
     protected void onClose()
     {
         closeConfigurationStore();
@@ -262,6 +277,18 @@
         }
     }
 
+    private void closeConfigurationStoreSafely()
+    {
+        try
+        {
+            closeConfigurationStore();
+        }
+        catch(Exception e)
+        {
+            LOGGER.warn("Unexpected exception on close of configuration store", e);
+        }
+    }
+
     @Override
     public String getVirtualHostInitialConfiguration()
     {
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/binding/BindingImplTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/binding/BindingImplTest.java
new file mode 100644
index 0000000..93fa911
--- /dev/null
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/binding/BindingImplTest.java
@@ -0,0 +1,76 @@
+/*
+ *
+ * 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.server.binding;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.qpid.common.AMQPFilterTypes;
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
+import org.apache.qpid.server.configuration.updater.TaskExecutor;
+import org.apache.qpid.server.exchange.ExchangeImpl;
+import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.Model;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class BindingImplTest extends QpidTestCase
+{
+    private TaskExecutor _taskExecutor;
+    private Model _model;
+
+    public void setUp() throws Exception
+    {
+        super.setUp();
+        _taskExecutor = CurrentThreadTaskExecutor.newStartedInstance();
+        _model = BrokerModel.getInstance();
+    }
+
+    public void testBindingValidationOnCreateWithInvalidSelector()
+    {
+        Map<String, String> arguments = new HashMap<>();
+        arguments.put(AMQPFilterTypes.JMS_SELECTOR.toString(), "test in (");
+        Map<String,Object> attributes = new HashMap<>();
+        attributes.put(Binding.ARGUMENTS, arguments);
+        attributes.put(Binding.NAME, getTestName());
+        AMQQueue queue = mock(AMQQueue.class);
+        when(queue.getTaskExecutor()).thenReturn(_taskExecutor);
+        when(queue.getModel()).thenReturn(_model);
+        ExchangeImpl exchange = mock(ExchangeImpl.class);
+        when(exchange.getTaskExecutor()).thenReturn(_taskExecutor);
+        when(exchange.getModel()).thenReturn(_model);
+        BindingImpl binding = new BindingImpl(attributes, queue, exchange);
+        try
+        {
+            binding.create();
+            fail("Exception is expected on validation with invalid selector");
+        }
+        catch (IllegalConfigurationException e)
+        {
+            assertTrue("Unexpected exception message " + e.getMessage(), e.getMessage().startsWith("Cannot parse JMS selector"));
+        }
+    }
+}
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/FileKeyStoreCreationTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/FileKeyStoreCreationTest.java
index 4b4891d..b4f9299 100644
--- a/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/FileKeyStoreCreationTest.java
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/FileKeyStoreCreationTest.java
@@ -63,7 +63,7 @@
         Map<String, Object> attributesCopy = new HashMap<String, Object>(attributes);
 
         Broker broker = mock(Broker.class);
-        TaskExecutor executor = new CurrentThreadTaskExecutor();
+        TaskExecutor executor = CurrentThreadTaskExecutor.newStartedInstance();
         when(broker.getObjectFactory()).thenReturn(_factory);
         when(broker.getModel()).thenReturn(_factory.getModel());
         when(broker.getTaskExecutor()).thenReturn(executor);
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java
index 36353f0..fbb08cd 100644
--- a/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java
@@ -34,6 +34,7 @@
 import java.util.Map;
 import java.util.UUID;
 
+import org.apache.qpid.server.model.BrokerShutdownProvider;
 import org.mockito.ArgumentCaptor;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
@@ -78,7 +79,8 @@
         _taskExecutor.start();
 
         _systemConfig = new JsonSystemConfigImpl(_taskExecutor, mock(EventLogger.class),
-                                               mock(LogRecorder.class), new BrokerOptions());
+                                               mock(LogRecorder.class), new BrokerOptions(),
+                                               mock(BrokerShutdownProvider.class));
 
 
         ConfiguredObjectRecord systemContextRecord = _systemConfig.asObjectRecord();
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/model/AbstractConfiguredObjectTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/model/AbstractConfiguredObjectTest.java
index e5c5a89..a1a363d 100644
--- a/java/broker-core/src/test/java/org/apache/qpid/server/model/AbstractConfiguredObjectTest.java
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/model/AbstractConfiguredObjectTest.java
@@ -26,7 +26,9 @@
 
 import junit.framework.TestCase;
 
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
 import org.apache.qpid.server.model.testmodel.TestChildCategory;
+import org.apache.qpid.server.model.testmodel.TestConfiguredObject;
 import org.apache.qpid.server.model.testmodel.TestModel;
 import org.apache.qpid.server.model.testmodel.TestRootCategory;
 import org.apache.qpid.server.store.ConfiguredObjectRecord;
@@ -257,4 +259,189 @@
                    parent.getChildren(TestChildCategory.class).isEmpty());
     }
 
+    public void testOpeningResultsInErroredStateWhenResolutionFails() throws Exception
+    {
+        TestConfiguredObject object = new TestConfiguredObject(getName());
+        object.setThrowExceptionOnPostResolve(true);
+        object.open();
+        assertFalse("Unexpected opened", object.isOpened());
+        assertEquals("Unexpected state", State.ERRORED, object.getState());
+
+        object.setThrowExceptionOnPostResolve(false);
+        object.setAttributes(Collections.<String, Object>singletonMap(Port.DESIRED_STATE, State.ACTIVE));
+        assertTrue("Unexpected opened", object.isOpened());
+        assertEquals("Unexpected state", State.ACTIVE, object.getState());
+    }
+
+    public void testOpeningInERROREDStateAfterFailedOpenOnDesiredStateChangeToActive() throws Exception
+    {
+        TestConfiguredObject object = new TestConfiguredObject(getName());
+        object.setThrowExceptionOnOpen(true);
+        object.open();
+        assertFalse("Unexpected opened", object.isOpened());
+        assertEquals("Unexpected state", State.ERRORED, object.getState());
+
+        object.setThrowExceptionOnOpen(false);
+        object.setAttributes(Collections.<String, Object>singletonMap(Port.DESIRED_STATE, State.ACTIVE));
+        assertTrue("Unexpected opened", object.isOpened());
+        assertEquals("Unexpected state", State.ACTIVE, object.getState());
+    }
+
+    public void testOpeningInERROREDStateAfterFailedOpenOnStart() throws Exception
+    {
+        TestConfiguredObject object = new TestConfiguredObject(getName());
+        object.setThrowExceptionOnOpen(true);
+        object.open();
+        assertFalse("Unexpected opened", object.isOpened());
+        assertEquals("Unexpected state", State.ERRORED, object.getState());
+
+        object.setThrowExceptionOnOpen(false);
+        object.start();
+        assertTrue("Unexpected opened", object.isOpened());
+        assertEquals("Unexpected state", State.ACTIVE, object.getState());
+    }
+
+    public void testDeletionERROREDStateAfterFailedOpenOnDelete() throws Exception
+    {
+        TestConfiguredObject object = new TestConfiguredObject(getName());
+        object.setThrowExceptionOnOpen(true);
+        object.open();
+        assertFalse("Unexpected opened", object.isOpened());
+        assertEquals("Unexpected state", State.ERRORED, object.getState());
+
+        object.delete();
+        assertFalse("Unexpected opened", object.isOpened());
+        assertEquals("Unexpected state", State.DELETED, object.getState());
+    }
+
+    public void testDeletionInERROREDStateAfterFailedOpenOnDesiredStateChangeToDelete() throws Exception
+    {
+        TestConfiguredObject object = new TestConfiguredObject(getName());
+        object.setThrowExceptionOnOpen(true);
+        object.open();
+        assertFalse("Unexpected opened", object.isOpened());
+        assertEquals("Unexpected state", State.ERRORED, object.getState());
+
+        object.setAttributes(Collections.<String, Object>singletonMap(Port.DESIRED_STATE, State.DELETED));
+        assertFalse("Unexpected opened", object.isOpened());
+        assertEquals("Unexpected state", State.DELETED, object.getState());
+    }
+
+
+    public void testCreationWithExceptionThrownFromValidationOnCreate() throws Exception
+    {
+        TestConfiguredObject object = new TestConfiguredObject(getName());
+        object.setThrowExceptionOnValidationOnCreate(true);
+        try
+        {
+            object.create();
+            fail("IllegalConfigurationException is expected to be thrown");
+        }
+        catch(IllegalConfigurationException e)
+        {
+            //pass
+        }
+        assertFalse("Unexpected opened", object.isOpened());
+    }
+
+    public void testCreationWithoutExceptionThrownFromValidationOnCreate() throws Exception
+    {
+        TestConfiguredObject object = new TestConfiguredObject(getName());
+        object.setThrowExceptionOnValidationOnCreate(false);
+        object.create();
+        assertTrue("Unexpected opened", object.isOpened());
+        assertEquals("Unexpected state", State.ACTIVE, object.getState());
+    }
+
+    public void testCreationWithExceptionThrownFromOnOpen() throws Exception
+    {
+        TestConfiguredObject object = new TestConfiguredObject(getName());
+        object.setThrowExceptionOnOpen(true);
+        try
+        {
+            object.create();
+            fail("Exception should have been re-thrown");
+        }
+        catch (RuntimeException re)
+        {
+            // pass
+        }
+
+        assertFalse("Unexpected opened", object.isOpened());
+        assertEquals("Unexpected state", State.DELETED, object.getState());
+    }
+
+    public void testCreationWithExceptionThrownFromOnCreate() throws Exception
+    {
+        TestConfiguredObject object = new TestConfiguredObject(getName());
+        object.setThrowExceptionOnCreate(true);
+        try
+        {
+            object.create();
+            fail("Exception should have been re-thrown");
+        }
+        catch (RuntimeException re)
+        {
+            // pass
+        }
+
+        assertFalse("Unexpected opened", object.isOpened());
+        assertEquals("Unexpected state", State.DELETED, object.getState());
+    }
+
+    public void testUnresolvedChildInERROREDStateIsNotValidatedOrOpenedOrAttainedDesiredStateOnParentOpen() throws Exception
+    {
+        TestConfiguredObject parent = new TestConfiguredObject("parent");
+        TestConfiguredObject child1 = new TestConfiguredObject("child1", parent, parent.getTaskExecutor());
+        child1.registerWithParents();
+        TestConfiguredObject child2 = new TestConfiguredObject("child2", parent, parent.getTaskExecutor());
+        child2.registerWithParents();
+
+        child1.setThrowExceptionOnPostResolve(true);
+
+        parent.open();
+
+        assertTrue("Parent should be resolved", parent.isResolved());
+        assertTrue("Parent should be validated", parent.isValidated());
+        assertTrue("Parent should be opened", parent.isOpened());
+        assertEquals("Unexpected parent state", State.ACTIVE, parent.getState());
+
+        assertTrue("Child2 should be resolved", child2.isResolved());
+        assertTrue("Child2 should be validated", child2.isValidated());
+        assertTrue("Child2 should be opened", child2.isOpened());
+        assertEquals("Unexpected child2 state", State.ACTIVE, child2.getState());
+
+        assertFalse("Child2 should not be resolved", child1.isResolved());
+        assertFalse("Child1 should not be validated", child1.isValidated());
+        assertFalse("Child1 should not be opened", child1.isOpened());
+        assertEquals("Unexpected child1 state", State.ERRORED, child1.getState());
+    }
+
+    public void testUnvalidatedChildInERROREDStateIsNotOpenedOrAttainedDesiredStateOnParentOpen() throws Exception
+    {
+        TestConfiguredObject parent = new TestConfiguredObject("parent");
+        TestConfiguredObject child1 = new TestConfiguredObject("child1", parent, parent.getTaskExecutor());
+        child1.registerWithParents();
+        TestConfiguredObject child2 = new TestConfiguredObject("child2", parent, parent.getTaskExecutor());
+        child2.registerWithParents();
+
+        child1.setThrowExceptionOnValidate(true);
+
+        parent.open();
+
+        assertTrue("Parent should be resolved", parent.isResolved());
+        assertTrue("Parent should be validated", parent.isValidated());
+        assertTrue("Parent should be opened", parent.isOpened());
+        assertEquals("Unexpected parent state", State.ACTIVE, parent.getState());
+
+        assertTrue("Child2 should be resolved", child2.isResolved());
+        assertTrue("Child2 should be validated", child2.isValidated());
+        assertTrue("Child2 should be opened", child2.isOpened());
+        assertEquals("Unexpected child2 state", State.ACTIVE, child2.getState());
+
+        assertTrue("Child1 should be resolved", child1.isResolved());
+        assertFalse("Child1 should not be validated", child1.isValidated());
+        assertFalse("Child1 should not be opened", child1.isOpened());
+        assertEquals("Unexpected child1 state", State.ERRORED, child1.getState());
+    }
 }
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java
index db5cf1a..ba6b0d9 100644
--- a/java/broker-core/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java
@@ -65,6 +65,7 @@
     private TaskExecutor _taskExecutor;
     private VirtualHostNode<?> _virtualHostNode;
     private DurableConfigurationStore _configStore;
+    private VirtualHost<?, ?, ?> _virtualHost;
 
     @Override
     protected void setUp() throws Exception
@@ -94,7 +95,17 @@
     {
         try
         {
-            _taskExecutor.stopImmediately();
+            try
+            {
+                _taskExecutor.stopImmediately();
+            }
+            finally
+            {
+                if (_virtualHost != null)
+                {
+                    _virtualHost.close();
+                }
+            }
         }
         finally
         {
@@ -386,6 +397,7 @@
 
         TestMemoryVirtualHost host = new TestMemoryVirtualHost(attributes, _virtualHostNode);
         host.create();
+        _virtualHost = host;
         return host;
     }
 
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImplTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImplTest.java
new file mode 100644
index 0000000..50a4e5a
--- /dev/null
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImplTest.java
@@ -0,0 +1,117 @@
+/*
+ *
+ * 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.server.model.adapter;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
+import org.apache.qpid.server.configuration.updater.TaskExecutor;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.security.SecurityManager;
+import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.test.utils.TestFileUtils;
+
+public class FileBasedGroupProviderImplTest extends QpidTestCase
+{
+    private TaskExecutor _taskExecutor;
+    private Broker _broker;
+    private File _groupFile;
+
+    @Override
+    public void setUp() throws Exception
+    {
+        super.setUp();
+        _taskExecutor = CurrentThreadTaskExecutor.newStartedInstance();
+
+        _broker = mock(Broker.class);
+        when(_broker.getTaskExecutor()).thenReturn(_taskExecutor);
+        when(_broker.getModel()).thenReturn(BrokerModel.getInstance());
+        when(_broker.getId()).thenReturn(UUID.randomUUID());
+        when(_broker.getSecurityManager()).thenReturn(new SecurityManager(_broker, false));
+    }
+
+    @Override
+    public void tearDown() throws Exception
+    {
+        try
+        {
+            if (_groupFile.exists())
+            {
+                _groupFile.delete();
+            }
+           _taskExecutor.stop();
+        }
+        finally
+        {
+            super.tearDown();
+        }
+    }
+
+    public void testValidationOnCreateWithInvalidPath()
+    {
+        Map<String,Object> attributes = new HashMap<>();
+        _groupFile = TestFileUtils.createTempFile(this, "groups");
+
+        String groupsFile = _groupFile.getAbsolutePath() + File.separator + "groups";
+        assertFalse("File should not exist", new File(groupsFile).exists());
+        attributes.put(FileBasedGroupProvider.PATH, groupsFile);
+        attributes.put(FileBasedGroupProvider.NAME, getTestName());
+
+        FileBasedGroupProviderImpl groupsProvider = new FileBasedGroupProviderImpl(attributes, _broker);
+        try
+        {
+            groupsProvider.create();
+            fail("Exception is expected on validation of groups provider with invalid path");
+        } catch (IllegalConfigurationException e)
+        {
+            assertEquals("Unexpected exception message:" + e.getMessage(), String.format("Cannot create groups file at '%s'", groupsFile), e.getMessage());
+        }
+    }
+
+    public void testValidationOnCreateWithInvalidGroups()
+    {
+        _groupFile = TestFileUtils.createTempFile(this, "groups", "=blah");
+        Map<String, Object> attributes = new HashMap<>();
+        String groupsFile = _groupFile.getAbsolutePath();
+        attributes.put(FileBasedGroupProvider.PATH, groupsFile);
+        attributes.put(FileBasedGroupProvider.NAME, getTestName());
+
+        FileBasedGroupProviderImpl groupsProvider = new FileBasedGroupProviderImpl(attributes, _broker);
+        try
+        {
+            groupsProvider.create();
+            fail("Exception is expected on validation of groups provider with invalid group file");
+        }
+        catch (IllegalConfigurationException e)
+        {
+            assertEquals("Unexpected exception message:" + e.getMessage(), String.format("Cannot load groups from '%s'", groupsFile), e.getMessage());
+        }
+    }
+
+}
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderTest.java
index 9bb004e..f532a93 100644
--- a/java/broker-core/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderTest.java
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderTest.java
@@ -31,6 +31,7 @@
 import java.util.Set;
 import java.util.UUID;
 
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
 import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
 import org.apache.qpid.server.configuration.updater.TaskExecutor;
 import org.apache.qpid.server.model.AuthenticationProvider;
@@ -109,7 +110,7 @@
             attributes.put(ConfiguredObject.ID, UUID.randomUUID());
             attributes.put(ConfiguredObject.NAME, getTestName());
             _preferencesProvider = new FileSystemPreferencesProviderImpl(attributes, _authenticationProvider);
-            _preferencesProvider.open();
+            _preferencesProvider.create();
 
             assertEquals(State.ACTIVE, _preferencesProvider.getState());
             assertTrue("Preferences file was not created", nonExistingFile.exists());
@@ -120,6 +121,57 @@
         }
     }
 
+    public void testValidationOnCreateForInvalidPath() throws Exception
+    {
+        File file = new File(TMP_FOLDER + File.separator + getTestName() + System.nanoTime() );
+        file.createNewFile();
+        String path = file.getAbsolutePath() + File.separator + "users";
+
+        Map<String, Object> attributes = new HashMap<String, Object>();
+        attributes.put(FileSystemPreferencesProvider.PATH, path);
+        attributes.put(ConfiguredObject.ID, UUID.randomUUID());
+        attributes.put(ConfiguredObject.NAME, getTestName());
+        _preferencesProvider = new FileSystemPreferencesProviderImpl(attributes, _authenticationProvider);
+
+        try
+        {
+
+            _preferencesProvider.create();
+
+            fail("Creation of preferences provider with invalid path should have failed");
+        }
+        catch(IllegalConfigurationException e)
+        {
+            assertEquals("Unexpected exception message:" + e.getMessage(), String.format("Cannot create preferences store file at '%s'", path), e.getMessage());
+        }
+    }
+
+    public void testValidationOnCreateWithInvalidPreferences()
+    {
+        File tmp = TestFileUtils.createTempFile(this, "preferences", "{blah:=boo}");
+        try
+        {
+            Map<String, Object> attributes = new HashMap<String, Object>();
+            attributes.put(FileSystemPreferencesProvider.PATH, tmp.getAbsolutePath());
+            attributes.put(ConfiguredObject.ID, UUID.randomUUID());
+            attributes.put(ConfiguredObject.NAME, getTestName());
+            _preferencesProvider = new FileSystemPreferencesProviderImpl(attributes, _authenticationProvider);
+            try
+            {
+                _preferencesProvider.create();
+                fail("Exception is expected on validation of groups provider with invalid preferences format");
+            }
+            catch (IllegalConfigurationException e)
+            {
+                assertEquals("Unexpected exception message:" + e.getMessage(), "Cannot parse preferences json in " + tmp.getName(), e.getMessage());
+            }
+        }
+        finally
+        {
+            tmp.delete();
+        }
+    }
+
     public void testConstructionWithEmptyFile() throws Exception
     {
         File emptyPrefsFile = new File(TMP_FOLDER, "preferences-" + getTestName() + ".json");
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java
index 523203c..642ea06 100644
--- a/java/broker-core/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java
@@ -54,7 +54,7 @@
 public class PortFactoryTest extends QpidTestCase
 {
     private UUID _portId = UUID.randomUUID();
-    private int _portNumber = 123;
+    private int _portNumber;
     private Set<String> _tcpStringSet = Collections.singleton(Transport.TCP.name());
     private Set<Transport> _tcpTransports = Collections.singleton(Transport.TCP);
     private Set<String> _sslStringSet = Collections.singleton(Transport.SSL.name());
@@ -68,11 +68,13 @@
     private String _authProviderName = "authProvider";
     private AuthenticationProvider _authProvider = mock(AuthenticationProvider.class);
     private ConfiguredObjectFactoryImpl _factory;
+    private Port<?> _port;
 
 
     @Override
     protected void setUp() throws Exception
     {
+        _portNumber = findFreePort();
         TaskExecutor executor = CurrentThreadTaskExecutor.newStartedInstance();
         when(_authProvider.getName()).thenReturn(_authProviderName);
         when(_broker.getChildren(eq(AuthenticationProvider.class))).thenReturn(Collections.singleton(_authProvider));
@@ -109,30 +111,45 @@
         _attributes.put(Port.BINDING_ADDRESS, "127.0.0.1");
     }
 
+    public void tearDown() throws Exception
+    {
+        try
+        {
+            if (_port != null)
+            {
+                _port.close();
+            }
+        }
+        finally
+        {
+            super.tearDown();
+        }
+    }
+
     public void testCreatePortWithMinimumAttributes()
     {
         Map<String, Object> attributes = new HashMap<String, Object>();
-        attributes.put(Port.PORT, 1);
+        attributes.put(Port.PORT, _portNumber);
         attributes.put(Port.NAME, getName());
         attributes.put(Port.AUTHENTICATION_PROVIDER, _authProviderName);
         attributes.put(Port.DESIRED_STATE, State.QUIESCED);
 
-        Port<?> port = _factory.create(Port.class, attributes, _broker);
+        _port = _factory.create(Port.class, attributes, _broker);
 
-        assertNotNull(port);
-        assertTrue(port instanceof AmqpPort);
-        assertEquals("Unexpected port", 1, port.getPort());
-        assertEquals("Unexpected transports", Collections.singleton(PortFactory.DEFAULT_TRANSPORT), port.getTransports());
+        assertNotNull(_port);
+        assertTrue(_port instanceof AmqpPort);
+        assertEquals("Unexpected _port", _portNumber, _port.getPort());
+        assertEquals("Unexpected transports", Collections.singleton(PortFactory.DEFAULT_TRANSPORT), _port.getTransports());
         assertEquals("Unexpected send buffer size", PortFactory.DEFAULT_AMQP_SEND_BUFFER_SIZE,
-                port.getAttribute(AmqpPort.SEND_BUFFER_SIZE));
+                _port.getAttribute(AmqpPort.SEND_BUFFER_SIZE));
         assertEquals("Unexpected receive buffer size", PortFactory.DEFAULT_AMQP_RECEIVE_BUFFER_SIZE,
-                port.getAttribute(AmqpPort.RECEIVE_BUFFER_SIZE));
+                _port.getAttribute(AmqpPort.RECEIVE_BUFFER_SIZE));
         assertEquals("Unexpected need client auth", PortFactory.DEFAULT_AMQP_NEED_CLIENT_AUTH,
-                port.getAttribute(Port.NEED_CLIENT_AUTH));
+                _port.getAttribute(Port.NEED_CLIENT_AUTH));
         assertEquals("Unexpected want client auth", PortFactory.DEFAULT_AMQP_WANT_CLIENT_AUTH,
-                port.getAttribute(Port.WANT_CLIENT_AUTH));
-        assertEquals("Unexpected tcp no delay", PortFactory.DEFAULT_AMQP_TCP_NO_DELAY, port.getAttribute(Port.TCP_NO_DELAY));
-        assertEquals("Unexpected binding", PortFactory.DEFAULT_AMQP_BINDING, port.getAttribute(Port.BINDING_ADDRESS));
+                _port.getAttribute(Port.WANT_CLIENT_AUTH));
+        assertEquals("Unexpected tcp no delay", PortFactory.DEFAULT_AMQP_TCP_NO_DELAY, _port.getAttribute(Port.TCP_NO_DELAY));
+        assertEquals("Unexpected binding", PortFactory.DEFAULT_AMQP_BINDING, _port.getAttribute(Port.BINDING_ADDRESS));
     }
 
     public void testCreateAmqpPort()
@@ -256,27 +273,27 @@
 
         _attributes.put(Port.DESIRED_STATE, State.QUIESCED);
 
-        Port<?> port = _factory.create(Port.class, _attributes, _broker);
+        _port = _factory.create(Port.class, _attributes, _broker);
 
-        assertNotNull(port);
-        assertTrue(port instanceof AmqpPort);
-        assertEquals(_portId, port.getId());
-        assertEquals(_portNumber, port.getPort());
+        assertNotNull(_port);
+        assertTrue(_port instanceof AmqpPort);
+        assertEquals(_portId, _port.getId());
+        assertEquals(_portNumber, _port.getPort());
         if(useSslTransport)
         {
-            assertEquals(_sslTransports, port.getTransports());
+            assertEquals(_sslTransports, _port.getTransports());
         }
         else
         {
-            assertEquals(_tcpTransports, port.getTransports());
+            assertEquals(_tcpTransports, _port.getTransports());
         }
-        assertEquals(amqp010ProtocolSet, port.getProtocols());
-        assertEquals("Unexpected send buffer size", 2, port.getAttribute(AmqpPort.SEND_BUFFER_SIZE));
-        assertEquals("Unexpected receive buffer size", 1, port.getAttribute(AmqpPort.RECEIVE_BUFFER_SIZE));
-        assertEquals("Unexpected need client auth", needClientAuth, port.getAttribute(Port.NEED_CLIENT_AUTH));
-        assertEquals("Unexpected want client auth", wantClientAuth, port.getAttribute(Port.WANT_CLIENT_AUTH));
-        assertEquals("Unexpected tcp no delay", true, port.getAttribute(Port.TCP_NO_DELAY));
-        assertEquals("Unexpected binding", "127.0.0.1", port.getAttribute(Port.BINDING_ADDRESS));
+        assertEquals(amqp010ProtocolSet, _port.getProtocols());
+        assertEquals("Unexpected send buffer size", 2, _port.getAttribute(AmqpPort.SEND_BUFFER_SIZE));
+        assertEquals("Unexpected receive buffer size", 1, _port.getAttribute(AmqpPort.RECEIVE_BUFFER_SIZE));
+        assertEquals("Unexpected need client auth", needClientAuth, _port.getAttribute(Port.NEED_CLIENT_AUTH));
+        assertEquals("Unexpected want client auth", wantClientAuth, _port.getAttribute(Port.WANT_CLIENT_AUTH));
+        assertEquals("Unexpected tcp no delay", true, _port.getAttribute(Port.TCP_NO_DELAY));
+        assertEquals("Unexpected binding", "127.0.0.1", _port.getAttribute(Port.BINDING_ADDRESS));
     }
 
     public void testCreateNonAmqpPort()
@@ -291,14 +308,14 @@
         _attributes.put(Port.NAME, getName());
         _attributes.put(Port.ID, _portId);
 
-        Port<?> port = _factory.create(Port.class, _attributes, _broker);
+        _port = _factory.create(Port.class, _attributes, _broker);
 
-        assertNotNull(port);
-        assertFalse("Port should not be an AMQP-specific subclass", port instanceof AmqpPort);
-        assertEquals(_portId, port.getId());
-        assertEquals(_portNumber, port.getPort());
-        assertEquals(_tcpTransports, port.getTransports());
-        assertEquals(nonAmqpProtocolSet, port.getProtocols());
+        assertNotNull(_port);
+        assertFalse("Port should not be an AMQP-specific subclass", _port instanceof AmqpPort);
+        assertEquals(_portId, _port.getId());
+        assertEquals(_portNumber, _port.getPort());
+        assertEquals(_tcpTransports, _port.getTransports());
+        assertEquals(nonAmqpProtocolSet, _port.getProtocols());
     }
 
     public void testCreateNonAmqpPortWithPartiallySetAttributes()
@@ -312,14 +329,14 @@
         _attributes.put(Port.NAME, getName());
         _attributes.put(Port.ID, _portId);
 
-        Port<?> port = _factory.create(Port.class, _attributes, _broker);
+        _port = _factory.create(Port.class, _attributes, _broker);
 
-        assertNotNull(port);
-        assertFalse("Port not be an AMQP-specific port subclass", port instanceof AmqpPort);
-        assertEquals(_portId, port.getId());
-        assertEquals(_portNumber, port.getPort());
-        assertEquals(Collections.singleton(PortFactory.DEFAULT_TRANSPORT), port.getTransports());
-        assertEquals(nonAmqpProtocolSet, port.getProtocols());
+        assertNotNull(_port);
+        assertFalse("Port not be an AMQP-specific _port subclass", _port instanceof AmqpPort);
+        assertEquals(_portId, _port.getId());
+        assertEquals(_portNumber, _port.getPort());
+        assertEquals(Collections.singleton(PortFactory.DEFAULT_TRANSPORT), _port.getTransports());
+        assertEquals(nonAmqpProtocolSet, _port.getProtocols());
 
     }
 
@@ -330,7 +347,7 @@
 
         try
         {
-            Port<?> port = _factory.create(Port.class, _attributes, _broker);
+            _port = _factory.create(Port.class, _attributes, _broker);
             fail("Exception not thrown");
         }
         catch (IllegalConfigurationException e)
@@ -353,7 +370,7 @@
 
         try
         {
-            Port<?> port = _factory.create(Port.class, attributes, _broker);
+            _port = _factory.create(Port.class, attributes, _broker);
             fail("RMI port creation should fail as another one already exist");
         }
         catch(IllegalConfigurationException e)
@@ -377,7 +394,7 @@
 
         try
         {
-            Port<?> port = _factory.create(Port.class, attributes, _broker);
+            _port = _factory.create(Port.class, attributes, _broker);
             fail("RMI port creation should fail due to requesting SSL");
         }
         catch(IllegalConfigurationException e)
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/model/port/AmqpPortImplTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/model/port/AmqpPortImplTest.java
new file mode 100644
index 0000000..1a993f8
--- /dev/null
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/model/port/AmqpPortImplTest.java
@@ -0,0 +1,123 @@
+/*
+ * 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.server.model.port;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
+import org.apache.qpid.server.configuration.updater.TaskExecutor;
+import org.apache.qpid.server.logging.EventLogger;
+import org.apache.qpid.server.model.AuthenticationProvider;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.Model;
+import org.apache.qpid.server.security.SecurityManager;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class AmqpPortImplTest extends QpidTestCase
+{
+    private static final String AUTHENTICATION_PROVIDER_NAME = "test";
+    private TaskExecutor _taskExecutor;
+    private Broker _broker;
+    private ServerSocket _socket;
+    private AmqpPortImpl _port;
+
+    @Override
+    public void setUp() throws Exception
+    {
+        super.setUp();
+        _taskExecutor = CurrentThreadTaskExecutor.newStartedInstance();
+        Model model = BrokerModel.getInstance();
+
+        _broker = mock(Broker.class);
+        when(_broker.getTaskExecutor()).thenReturn(_taskExecutor);
+        when(_broker.getModel()).thenReturn(model);
+        when(_broker.getId()).thenReturn(UUID.randomUUID());
+        when(_broker.getSecurityManager()).thenReturn(new SecurityManager(_broker, false));
+        when(_broker.getCategoryClass()).thenReturn(Broker.class);
+        when(_broker.getEventLogger()).thenReturn(new EventLogger());
+        AuthenticationProvider<?> provider = mock(AuthenticationProvider.class);
+        when(provider.getName()).thenReturn(AUTHENTICATION_PROVIDER_NAME);
+        when(provider.getParent(Broker.class)).thenReturn(_broker);
+        when(_broker.getChildren(AuthenticationProvider.class)).thenReturn(Collections.<AuthenticationProvider>singleton(provider));
+        when(_broker.getChildByName(AuthenticationProvider.class, AUTHENTICATION_PROVIDER_NAME)).thenReturn(provider);
+    }
+
+    @Override
+    public void tearDown() throws Exception
+    {
+        try
+        {
+            if (_socket != null)
+            {
+                _socket.close();
+            }
+            _taskExecutor.stop();
+        }
+        finally
+        {
+            if (_port != null)
+            {
+                _port.close();
+            }
+            super.tearDown();
+        }
+    }
+
+    public void testValidateOnCreate() throws Exception
+    {
+        _socket = openSocket();
+
+        Map<String, Object> attributes = new HashMap<>();
+        attributes.put(AmqpPort.PORT, _socket.getLocalPort());
+        attributes.put(AmqpPort.NAME, getTestName());
+        attributes.put(AmqpPort.AUTHENTICATION_PROVIDER, AUTHENTICATION_PROVIDER_NAME);
+        _port = new AmqpPortImpl(attributes, _broker);
+        try
+        {
+            _port.create();
+            fail("Creation should fail due to validation check");
+        }
+        catch (IllegalConfigurationException e)
+        {
+            assertEquals("Unexpected exception message",
+                    String.format("Cannot bind to port %d and binding address '%s'. Port is already is use.",
+                        _socket.getLocalPort(), "*"), e.getMessage());
+        }
+    }
+
+    private ServerSocket openSocket() throws IOException
+    {
+        ServerSocket serverSocket = new ServerSocket();
+        serverSocket.setReuseAddress(true);
+        serverSocket.bind(new InetSocketAddress(findFreePort()));
+        return serverSocket;
+    }
+}
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestConfiguredObject.java b/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestConfiguredObject.java
new file mode 100644
index 0000000..5c04db0
--- /dev/null
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestConfiguredObject.java
@@ -0,0 +1,256 @@
+/*
+ * 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.server.model.testmodel;
+
+import static org.mockito.Mockito.mock;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
+import org.apache.qpid.server.configuration.updater.TaskExecutor;
+import org.apache.qpid.server.model.AbstractConfiguredObject;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.ConfiguredObjectFactory;
+import org.apache.qpid.server.model.ConfiguredObjectFactoryImpl;
+import org.apache.qpid.server.model.ConfiguredObjectTypeRegistry;
+import org.apache.qpid.server.model.ManagedObject;
+import org.apache.qpid.server.model.Model;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.StateTransition;
+import org.apache.qpid.server.plugin.ConfiguredObjectRegistration;
+
+@ManagedObject
+public class TestConfiguredObject extends AbstractConfiguredObject
+{
+    private boolean _opened;
+    private boolean _validated;
+    private boolean _resolved;
+    private boolean _throwExceptionOnOpen;
+    private boolean _throwExceptionOnValidationOnCreate;
+    private boolean _throwExceptionOnPostResolve;
+    private boolean _throwExceptionOnCreate;
+    private boolean _throwExceptionOnValidate;
+
+    public final static Map<Class<? extends ConfiguredObject>, ConfiguredObject<?>> createParents(ConfiguredObject<?> parent)
+    {
+        return Collections.<Class<? extends ConfiguredObject>, ConfiguredObject<?>>singletonMap(parent.getCategoryClass(), parent);
+    }
+
+    public TestConfiguredObject(String name)
+    {
+        this(name, mock(ConfiguredObject.class), CurrentThreadTaskExecutor.newStartedInstance());
+    }
+
+    public TestConfiguredObject(String name, ConfiguredObject<?> parent, TaskExecutor taskExecutor)
+    {
+        this(createParents(parent), Collections.<String, Object>singletonMap(ConfiguredObject.NAME, name), taskExecutor, TestConfiguredObjectModel.INSTANCE);
+    }
+
+    public TestConfiguredObject(Map parents, Map<String, Object> attributes, TaskExecutor taskExecutor, Model model)
+    {
+        super(parents, attributes, taskExecutor, model);
+        _opened = false;
+    }
+
+    @Override
+    protected void postResolve()
+    {
+        if (_throwExceptionOnPostResolve)
+        {
+            throw new IllegalConfigurationException("Cannot resolve");
+        }
+        _resolved = true;
+    }
+
+    @Override
+    protected void onCreate()
+    {
+        if (_throwExceptionOnCreate)
+        {
+            throw new IllegalConfigurationException("Cannot create");
+        }
+    }
+
+    @Override
+    protected void onOpen()
+    {
+        if (_throwExceptionOnOpen)
+        {
+            throw new IllegalConfigurationException("Cannot open");
+        }
+        _opened = true;
+    }
+
+    @Override
+    protected void validateOnCreate()
+    {
+        if (_throwExceptionOnValidationOnCreate)
+        {
+            throw new IllegalConfigurationException("Cannot validate on create");
+        }
+    }
+
+    @Override
+    public void onValidate()
+    {
+        if (_throwExceptionOnValidate)
+        {
+            throw new IllegalConfigurationException("Cannot validate");
+        }
+        _validated = true;
+    }
+
+    @StateTransition( currentState = {State.ERRORED, State.UNINITIALIZED}, desiredState = State.ACTIVE )
+    protected void activate()
+    {
+        setState(State.ACTIVE);
+    }
+
+    @StateTransition( currentState = {State.ERRORED, State.UNINITIALIZED}, desiredState = State.DELETED )
+    protected void doDelete()
+    {
+        setState(State.DELETED);
+    }
+
+    public boolean isOpened()
+    {
+        return _opened;
+    }
+
+    public void setThrowExceptionOnOpen(boolean throwException)
+    {
+        _throwExceptionOnOpen = throwException;
+    }
+
+    public void setThrowExceptionOnValidationOnCreate(boolean throwException)
+    {
+        _throwExceptionOnValidationOnCreate = throwException;
+    }
+
+    public void setThrowExceptionOnPostResolve(boolean throwException)
+    {
+        _throwExceptionOnPostResolve = throwException;
+    }
+
+    public void setThrowExceptionOnCreate(boolean throwExceptionOnCreate)
+    {
+        _throwExceptionOnCreate = throwExceptionOnCreate;
+    }
+
+    public void setThrowExceptionOnValidate(boolean throwException)
+    {
+        _throwExceptionOnValidate= throwException;
+    }
+
+    public boolean isValidated()
+    {
+        return _validated;
+    }
+
+    public boolean isResolved()
+    {
+        return _resolved;
+    }
+
+    public static class TestConfiguredObjectModel extends  Model
+    {
+
+        private Collection<Class<? extends ConfiguredObject>> CATEGORIES = Collections.<Class<? extends ConfiguredObject>>singleton(TestConfiguredObject.class);
+        private ConfiguredObjectFactoryImpl _configuredObjectFactory;
+
+        private static TestConfiguredObjectModel INSTANCE = new TestConfiguredObjectModel();
+        private ConfiguredObjectTypeRegistry _configuredObjectTypeRegistry;
+
+        private TestConfiguredObjectModel()
+        {
+            _configuredObjectFactory = new ConfiguredObjectFactoryImpl(this);
+            ConfiguredObjectRegistration configuredObjectRegistration = new ConfiguredObjectRegistration()
+            {
+                @Override
+                public Collection<Class<? extends ConfiguredObject>> getConfiguredObjectClasses()
+                {
+                    return CATEGORIES;
+                }
+
+                @Override
+                public String getType()
+                {
+                    return TestConfiguredObjectModel.class.getSimpleName();
+                }
+            };
+            _configuredObjectTypeRegistry = new ConfiguredObjectTypeRegistry(Arrays.asList(configuredObjectRegistration), CATEGORIES);
+        }
+
+        @Override
+        public Collection<Class<? extends ConfiguredObject>> getSupportedCategories()
+        {
+            return CATEGORIES;
+        }
+
+        @Override
+        public Collection<Class<? extends ConfiguredObject>> getChildTypes(Class<? extends ConfiguredObject> parent)
+        {
+            return TestConfiguredObject.class.isAssignableFrom(parent)
+                    ? CATEGORIES
+                    : Collections.<Class<? extends ConfiguredObject>>emptySet();
+        }
+
+        @Override
+        public Class<? extends ConfiguredObject> getRootCategory()
+        {
+            return TestConfiguredObject.class;
+        }
+
+        @Override
+        public Collection<Class<? extends ConfiguredObject>> getParentTypes(final Class<? extends ConfiguredObject> child)
+        {
+            return TestConfiguredObject.class.isAssignableFrom(child)
+                    ? CATEGORIES
+                    : Collections.<Class<? extends ConfiguredObject>>emptySet();
+        }
+
+        @Override
+        public int getMajorVersion()
+        {
+            return 99;
+        }
+
+        @Override
+        public int getMinorVersion()
+        {
+            return 99;
+        }
+
+        @Override
+        public ConfiguredObjectFactory getObjectFactory()
+        {
+            return _configuredObjectFactory;
+        }
+
+        @Override
+        public ConfiguredObjectTypeRegistry getTypeRegistry()
+        {
+            return _configuredObjectTypeRegistry;
+        }
+    }
+}
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java
index 703a8d4..84ba7a3 100644
--- a/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java
@@ -90,31 +90,28 @@
 
     private void setupMocks() throws Exception
     {
-        _principalDatabase = mock(PrincipalDatabase.class);
-
-        when(_principalDatabase.getMechanisms()).thenReturn(Collections.singletonList(MOCK_MECH_NAME));
-        when(_principalDatabase.createSaslServer(MOCK_MECH_NAME, LOCALHOST, null)).thenReturn(new MySaslServer(false, true));
+        setUpPrincipalDatabase();
 
         setupManager(false);
 
         _manager.initialise();
     }
 
+    private void setUpPrincipalDatabase() throws SaslException
+    {
+        _principalDatabase = mock(PrincipalDatabase.class);
+
+        when(_principalDatabase.getMechanisms()).thenReturn(Collections.singletonList(MOCK_MECH_NAME));
+        when(_principalDatabase.createSaslServer(MOCK_MECH_NAME, LOCALHOST, null)).thenReturn(new MySaslServer(false, true));
+    }
+
     private void setupManager(final boolean recovering)
     {
         Map<String,Object> attrs = new HashMap<String, Object>();
         attrs.put(ConfiguredObject.ID, UUID.randomUUID());
         attrs.put(ConfiguredObject.NAME, getTestName());
         attrs.put("path", _passwordFileLocation);
-        _manager = new PrincipalDatabaseAuthenticationManager(attrs, BrokerTestHelper.createBrokerMock())
-        {
-            @Override
-            protected PrincipalDatabase createDatabase()
-            {
-                return _principalDatabase;
-            }
-
-        };
+        _manager = getPrincipalDatabaseAuthenticationManager(attrs);
         if(recovering)
         {
             _manager.open();
@@ -273,6 +270,41 @@
         assertFalse("Password file was not deleted", new File(_passwordFileLocation).exists());
     }
 
+    public void testCreateForInvalidPath() throws Exception
+    {
+        setUpPrincipalDatabase();
+
+        Map<String,Object> attrs = new HashMap<>();
+        attrs.put(ConfiguredObject.ID, UUID.randomUUID());
+        attrs.put(ConfiguredObject.NAME, getTestName());
+        String path = TMP_FOLDER + File.separator + getTestName() + System.nanoTime() + File.separator + "users";
+        attrs.put("path", path);
+
+        _manager = getPrincipalDatabaseAuthenticationManager(attrs);
+        try
+        {
+            _manager.create();
+            fail("Creation with invalid path should have failed");
+        }
+        catch(IllegalConfigurationException e)
+        {
+            assertEquals("Unexpected exception message:" + e.getMessage(), String.format("Cannot create password file at '%s'", path), e.getMessage());
+        }
+    }
+
+    PrincipalDatabaseAuthenticationManager getPrincipalDatabaseAuthenticationManager(final Map<String, Object> attrs)
+    {
+        return new PrincipalDatabaseAuthenticationManager(attrs, BrokerTestHelper.createBrokerMock())
+        {
+            @Override
+            protected PrincipalDatabase createDatabase()
+            {
+                return _principalDatabase;
+            }
+
+        };
+    }
+
     private void deletePasswordFileIfExists()
     {
         File passwordFile = new File(_passwordFileLocation);
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerFactoryTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerFactoryTest.java
index 6001ed1..9e580d3 100644
--- a/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerFactoryTest.java
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerFactoryTest.java
@@ -57,40 +57,15 @@
         _configuration.put(AuthenticationProvider.NAME, getName());
     }
 
-    public void testLdapInstanceCreated() throws Exception
-    {
-        _configuration.put(AuthenticationProvider.TYPE, SimpleLDAPAuthenticationManager.PROVIDER_TYPE);
-        _configuration.put("providerUrl", "ldap://example.com:389/");
-        _configuration.put("searchContext", "dc=example");
-
-        AuthenticationProvider manager = _factory.create(AuthenticationProvider.class, _configuration, _broker);
-        assertNotNull(manager);
-
-    }
-
-    public void testLdapsInstanceCreated() throws Exception
+    public void testLdapCreated() throws Exception
     {
         _configuration.put(AuthenticationProvider.TYPE, SimpleLDAPAuthenticationManager.PROVIDER_TYPE);
         _configuration.put("providerUrl", "ldaps://example.com:636/");
         _configuration.put("searchContext", "dc=example");
+        _configuration.put("searchFilter", "(uid={0})");
+        _configuration.put("ldapContextFactory", TestLdapDirectoryContext.class.getName());
 
-        AuthenticationProvider manager = _factory.create(AuthenticationProvider.class, _configuration, _broker);
-        assertNotNull(manager);
-
-    }
-
-    public void testLdapsWithTrustStoreInstanceCreated() throws Exception
-    {
-        when(_broker.getChildren(eq(TrustStore.class))).thenReturn(Collections.singletonList(_trustStore));
-
-
-        _configuration.put(AuthenticationProvider.TYPE, SimpleLDAPAuthenticationManager.PROVIDER_TYPE);
-        _configuration.put("providerUrl", "ldaps://example.com:636/");
-        _configuration.put("searchContext", "dc=example");
-        _configuration.put("trustStore", "mytruststore");
-
-        AuthenticationProvider manager = _factory.create(AuthenticationProvider.class, _configuration, _broker);
-        assertNotNull(manager);
+        _factory.create(AuthenticationProvider.class, _configuration, _broker);
     }
 
     public void testLdapsWhenTrustStoreNotFound() throws Exception
@@ -100,6 +75,7 @@
         _configuration.put(AuthenticationProvider.TYPE, SimpleLDAPAuthenticationManager.PROVIDER_TYPE);
         _configuration.put("providerUrl", "ldaps://example.com:636/");
         _configuration.put("searchContext", "dc=example");
+        _configuration.put("searchFilter", "(uid={0})");
         _configuration.put("trustStore", "notfound");
 
         try
@@ -110,7 +86,7 @@
         catch(IllegalArgumentException e)
         {
             // PASS
-            assertTrue("Message does not include underlying issue", e.getMessage().contains("name 'notfound'"));
+            assertTrue("Message does not include underlying issue ", e.getMessage().contains("name 'notfound'"));
             assertTrue("Message does not include the attribute name", e.getMessage().contains("trustStore"));
             assertTrue("Message does not include the expected type", e.getMessage().contains("TrustStore"));
         }
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/TestLdapDirectoryContext.java b/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/TestLdapDirectoryContext.java
new file mode 100644
index 0000000..87b73c8
--- /dev/null
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/TestLdapDirectoryContext.java
@@ -0,0 +1,38 @@
+/*
+ * 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.server.security.auth.manager;
+
+import static org.mockito.Mockito.mock;
+
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.directory.DirContext;
+
+public class TestLdapDirectoryContext implements javax.naming.spi.InitialContextFactory
+{
+    @Override
+    public Context getInitialContext(final Hashtable<?, ?> environment) throws NamingException
+    {
+        return (DirContext)mock(DirContext.class);
+    }
+
+}
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerRecovererTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerRecovererTest.java
index 52f70e7..c220876 100644
--- a/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerRecovererTest.java
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerRecovererTest.java
@@ -21,7 +21,9 @@
 package org.apache.qpid.server.store;
 
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
 
 import java.util.Arrays;
 import java.util.Collections;
@@ -40,6 +42,7 @@
 import org.apache.qpid.server.model.AuthenticationProvider;
 import org.apache.qpid.server.model.Broker;
 import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.BrokerShutdownProvider;
 import org.apache.qpid.server.model.ConfiguredObject;
 import org.apache.qpid.server.model.GroupProvider;
 import org.apache.qpid.server.model.JsonSystemConfigImpl;
@@ -55,6 +58,7 @@
     private UUID _authenticationProvider1Id = UUID.randomUUID();
     private SystemConfig<?> _systemConfig;
     private TaskExecutor _taskExecutor;
+    private BrokerShutdownProvider _brokerShutdownProvider;
 
     @Override
     protected void setUp() throws Exception
@@ -63,8 +67,11 @@
 
         _taskExecutor = new CurrentThreadTaskExecutor();
         _taskExecutor.start();
+        _brokerShutdownProvider = mock(BrokerShutdownProvider.class);
         _systemConfig = new JsonSystemConfigImpl(_taskExecutor,
-                                               mock(EventLogger.class), mock(LogRecorder.class), new BrokerOptions());
+                                               mock(EventLogger.class), mock(LogRecorder.class),
+                                               new BrokerOptions(),
+                                               _brokerShutdownProvider);
 
         when(_brokerEntry.getId()).thenReturn(_brokerId);
         when(_brokerEntry.getType()).thenReturn(Broker.class.getSimpleName());
@@ -251,18 +258,10 @@
             brokerAttributes.put(Broker.NAME, getName());
             when(_brokerEntry.getAttributes()).thenReturn(brokerAttributes);
 
-            try
-            {
-                resolveObjects(_brokerEntry);
-                Broker<?> broker = _systemConfig.getBroker();
-                broker.open();
-                fail("The broker creation should fail due to unsupported model version");
-            }
-            catch (IllegalConfigurationException e)
-            {
-                assertEquals("The model version '" + incompatibleVersion
-                        + "' in configuration is incompatible with the broker model version '" + BrokerModel.MODEL_VERSION + "'", e.getMessage());
-            }
+            resolveObjects(_brokerEntry);
+            Broker<?> broker = _systemConfig.getBroker();
+            broker.open();
+            verify(_brokerShutdownProvider).shutdown();
         }
     }
 
@@ -276,20 +275,12 @@
 
         when(_brokerEntry.getAttributes()).thenReturn(brokerAttributes);
 
-        try
-        {
-            UnresolvedConfiguredObject<? extends ConfiguredObject> recover =
-                    _systemConfig.getObjectFactory().recover(_brokerEntry, _systemConfig);
+        UnresolvedConfiguredObject<? extends ConfiguredObject> recover =
+                _systemConfig.getObjectFactory().recover(_brokerEntry, _systemConfig);
 
-            Broker<?> broker = (Broker<?>) recover.resolve();
-            broker.open();
-            fail("The broker creation should fail due to unsupported model version");
-        }
-        catch (IllegalConfigurationException e)
-        {
-            assertEquals("The model version '" + incompatibleVersion
-                    + "' in configuration is incompatible with the broker model version '" + BrokerModel.MODEL_VERSION + "'", e.getMessage());
-        }
+        Broker<?> broker = (Broker<?>) recover.resolve();
+        broker.open();
+        verify(_brokerShutdownProvider).shutdown();
     }
 
     public void testIncorrectModelVersion() throws Exception
@@ -303,18 +294,12 @@
             brokerAttributes.put(Broker.MODEL_VERSION, modelVersion);
             when(_brokerEntry.getAttributes()).thenReturn(brokerAttributes);
 
-            try
-            {
-                UnresolvedConfiguredObject<? extends ConfiguredObject> recover =
-                        _systemConfig.getObjectFactory().recover(_brokerEntry, _systemConfig);
-                Broker<?> broker = (Broker<?>) recover.resolve();
-                broker.open();
-                fail("The broker creation should fail due to unsupported model version");
-            }
-            catch (IllegalConfigurationException e)
-            {
-                // pass
-            }
+            UnresolvedConfiguredObject<? extends ConfiguredObject> recover =
+                    _systemConfig.getObjectFactory().recover(_brokerEntry, _systemConfig);
+            Broker<?> broker = (Broker<?>) recover.resolve();
+            broker.open();
+            verify(_brokerShutdownProvider).shutdown();
+            reset(_brokerShutdownProvider);
         }
     }
 
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecovererTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecovererTest.java
index c94a0ef..45b595b 100644
--- a/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecovererTest.java
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecovererTest.java
@@ -32,6 +32,7 @@
 import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
 import org.apache.qpid.server.logging.EventLogger;
 import org.apache.qpid.server.logging.LogRecorder;
+import org.apache.qpid.server.model.BrokerShutdownProvider;
 import org.apache.qpid.server.model.ConfiguredObject;
 import org.apache.qpid.server.model.JsonSystemConfigImpl;
 import org.apache.qpid.server.model.SystemConfig;
@@ -60,7 +61,8 @@
         _systemConfig = new JsonSystemConfigImpl(_taskExecutor,
                                                mock(EventLogger.class),
                                                mock(LogRecorder.class),
-                                               new BrokerOptions());
+                                               new BrokerOptions(),
+                                               mock(BrokerShutdownProvider.class));
     }
 
     public void testUpgradeVirtualHostWithJDBCStoreAndBoneCPPool()
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/AbstractVirtualHostTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/AbstractVirtualHostTest.java
new file mode 100644
index 0000000..889097f
--- /dev/null
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/AbstractVirtualHostTest.java
@@ -0,0 +1,247 @@
+/*
+ *
+ * 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.server.virtualhost;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.doThrow;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.configuration.updater.TaskExecutor;
+import org.apache.qpid.server.configuration.updater.TaskExecutorImpl;
+import org.apache.qpid.server.logging.EventLogger;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.SystemConfig;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.model.VirtualHostNode;
+import org.apache.qpid.server.security.SecurityManager;
+import org.apache.qpid.server.store.DurableConfigurationStore;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.test.utils.QpidTestCase;
+import org.mockito.verification.VerificationMode;
+
+public class AbstractVirtualHostTest extends QpidTestCase
+{
+    private TaskExecutor _taskExecutor;
+    private VirtualHostNode<?> _node;
+    private MessageStore _failingStore;
+
+    @Override
+    public void setUp() throws Exception
+    {
+        super.setUp();
+
+        SystemConfig systemConfig = mock(SystemConfig.class);
+        when(systemConfig.getEventLogger()).thenReturn(mock(EventLogger.class));
+        Broker<?> broker = mock(Broker.class);
+        when(broker.getParent(SystemConfig.class)).thenReturn(systemConfig);
+        when(broker.getSecurityManager()).thenReturn(new SecurityManager(broker, false));
+
+        _taskExecutor = new TaskExecutorImpl();
+        _taskExecutor.start();
+        when(broker.getTaskExecutor()).thenReturn(_taskExecutor);
+
+        _node = mock(VirtualHostNode.class);
+        when(_node.getParent(Broker.class)).thenReturn(broker);
+        when(_node.getModel()).thenReturn(BrokerModel.getInstance());
+        when(_node.getTaskExecutor()).thenReturn(_taskExecutor);
+        when(_node.getConfigurationStore()).thenReturn(mock(DurableConfigurationStore.class));
+
+        _failingStore = mock(MessageStore.class);
+        doThrow(new RuntimeException("Cannot open store")).when(_failingStore).openMessageStore(any(ConfiguredObject.class));
+    }
+
+    @Override
+    public void  tearDown() throws Exception
+    {
+        try
+        {
+            if (_taskExecutor != null)
+            {
+                _taskExecutor.stopImmediately();
+            }
+        }
+        finally
+        {
+            super.tearDown();
+        }
+    }
+
+    public void testValidateOnCreateFails()
+    {
+        Map<String,Object> attributes = Collections.<String, Object>singletonMap(AbstractVirtualHost.NAME, getTestName());
+
+        AbstractVirtualHost host = new AbstractVirtualHost(attributes, _node)
+        {
+            @Override
+            protected MessageStore createMessageStore()
+            {
+                return _failingStore;
+            }
+        };
+
+        try
+        {
+            host.validateOnCreate();
+            fail("Validation on creation should fail");
+        }
+        catch(IllegalConfigurationException e)
+        {
+            assertTrue("Unexpected exception " + e.getMessage(), e.getMessage().startsWith("Cannot open virtual host message store"));
+        }
+    }
+
+    public void testValidateOnCreateSucceeds()
+    {
+        Map<String,Object> attributes = Collections.<String, Object>singletonMap(AbstractVirtualHost.NAME, getTestName());
+        final MessageStore store = mock(MessageStore.class);
+        AbstractVirtualHost host = new AbstractVirtualHost(attributes, _node)
+        {
+            @Override
+            protected MessageStore createMessageStore()
+            {
+                return store;
+            }
+        };
+
+        host.validateOnCreate();
+        verify(store).openMessageStore(host);
+        verify(store).closeMessageStore();
+    }
+
+    public void testOpenFails()
+    {
+        Map<String,Object> attributes = Collections.<String, Object>singletonMap(AbstractVirtualHost.NAME, getTestName());
+
+        AbstractVirtualHost host = new AbstractVirtualHost(attributes, _node)
+        {
+            @Override
+            protected MessageStore createMessageStore()
+            {
+                return _failingStore;
+            }
+        };
+
+        host.open();
+        assertEquals("Unexpected host state", State.ERRORED, host.getState());
+    }
+
+    public void testOpenSucceeds()
+    {
+        Map<String,Object> attributes = Collections.<String, Object>singletonMap(AbstractVirtualHost.NAME, getTestName());
+        final MessageStore store = mock(MessageStore.class);
+        AbstractVirtualHost host = new AbstractVirtualHost(attributes, _node)
+        {
+            @Override
+            protected MessageStore createMessageStore()
+            {
+                return  store;
+            }
+        };
+
+        host.open();
+        assertEquals("Unexpected host state", State.ACTIVE, host.getState());
+        verify(store).openMessageStore(host);
+
+        // make sure that method AbstractVirtualHost.onExceptionInOpen was not called
+        verify(store, times(0)).closeMessageStore();
+    }
+
+    public void testDeleteInErrorStateAfterOpen()
+    {
+        Map<String,Object> attributes = Collections.<String, Object>singletonMap(AbstractVirtualHost.NAME, getTestName());
+        AbstractVirtualHost host = new AbstractVirtualHost(attributes, _node)
+        {
+            @Override
+            protected MessageStore createMessageStore()
+            {
+                return  _failingStore;
+            }
+        };
+
+        host.open();
+
+        assertEquals("Unexpected state", State.ERRORED, host.getState());
+
+        host.delete();
+        assertEquals("Unexpected state", State.DELETED, host.getState());
+    }
+
+    public void testActivateInErrorStateAfterOpen() throws Exception
+    {
+        Map<String,Object> attributes = Collections.<String, Object>singletonMap(AbstractVirtualHost.NAME, getTestName());
+        final MessageStore store = mock(MessageStore.class);
+        doThrow(new RuntimeException("Cannot open store")).when(store).openMessageStore(any(ConfiguredObject.class));
+        AbstractVirtualHost host = new AbstractVirtualHost(attributes, _node)
+        {
+            @Override
+            protected MessageStore createMessageStore()
+            {
+                return  store;
+            }
+        };
+
+        host.open();
+        assertEquals("Unexpected state", State.ERRORED, host.getState());
+
+        doNothing().when(store).openMessageStore(any(ConfiguredObject.class));
+
+        host.setAttributes(Collections.<String, Object>singletonMap(VirtualHost.DESIRED_STATE, State.ACTIVE));
+        assertEquals("Unexpected state", State.ACTIVE, host.getState());
+    }
+
+    public void testStartInErrorStateAfterOpen() throws Exception
+    {
+        Map<String,Object> attributes = Collections.<String, Object>singletonMap(AbstractVirtualHost.NAME, getTestName());
+        final MessageStore store = mock(MessageStore.class);
+        doThrow(new RuntimeException("Cannot open store")).when(store).openMessageStore(any(ConfiguredObject.class));
+        AbstractVirtualHost host = new AbstractVirtualHost(attributes, _node)
+        {
+            @Override
+            protected MessageStore createMessageStore()
+            {
+                return  store;
+            }
+        };
+
+        host.open();
+        assertEquals("Unexpected state", State.ERRORED, host.getState());
+
+        doNothing().when(store).openMessageStore(any(ConfiguredObject.class));
+
+        host.start();
+        assertEquals("Unexpected state", State.ACTIVE, host.getState());
+    }
+}
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java
index 971c96b..b17f383 100644
--- a/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java
@@ -20,22 +20,30 @@
  */
 package org.apache.qpid.server.virtualhostnode;
 
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import java.security.AccessControlException;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.UUID;
+import java.util.concurrent.atomic.AtomicBoolean;
 
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
 import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
 import org.apache.qpid.server.configuration.updater.TaskExecutor;
 import org.apache.qpid.server.model.Broker;
 import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.ConfiguredObject;
 import org.apache.qpid.server.model.ConfiguredObjectFactoryImpl;
 import org.apache.qpid.server.model.Model;
+import org.apache.qpid.server.model.RemoteReplicationNode;
 import org.apache.qpid.server.model.State;
 import org.apache.qpid.server.model.SystemConfig;
 import org.apache.qpid.server.model.VirtualHost;
@@ -348,6 +356,132 @@
         assertEquals("Virtual host node state changed unexpectedly", State.ACTIVE, node.getState());
     }
 
+    public void testValidateOnCreateFails() throws Exception
+    {
+        String nodeName = getTestName();
+        Map<String, Object> attributes = Collections.<String, Object>singletonMap(TestVirtualHostNode.NAME, nodeName);
+
+        final DurableConfigurationStore store = mock(DurableConfigurationStore.class);
+        doThrow(new RuntimeException("Cannot open store")).when(store).openConfigurationStore(any(ConfiguredObject.class), any(boolean.class));
+        AbstractStandardVirtualHostNode node = createAbstractStandardVirtualHostNode(attributes, store);
+
+        try
+        {
+            node.validateOnCreate();
+            fail("Cannot create node");
+        }
+        catch (IllegalConfigurationException e)
+        {
+            assertTrue("Unexpected exception " + e.getMessage(), e.getMessage().startsWith("Cannot open node configuration store"));
+        }
+    }
+
+    public void testValidateOnCreateSucceeds() throws Exception
+    {
+        String nodeName = getTestName();
+        Map<String, Object> attributes = Collections.<String, Object>singletonMap(TestVirtualHostNode.NAME, nodeName);
+
+        final DurableConfigurationStore store = mock(DurableConfigurationStore.class);
+        AbstractStandardVirtualHostNode node = createAbstractStandardVirtualHostNode(attributes, store);
+
+        node.validateOnCreate();
+        verify(store).openConfigurationStore(node, false);
+        verify(store).closeConfigurationStore();
+    }
+
+    public void testOpenFails() throws Exception
+    {
+        String nodeName = getTestName();
+        Map<String, Object> attributes = Collections.<String, Object>singletonMap(TestVirtualHostNode.NAME, nodeName);
+
+        DurableConfigurationStore store = mock(DurableConfigurationStore.class);
+        AbstractVirtualHostNode node = new TestAbstractVirtualHostNode( _broker, attributes, store);
+        node.open();
+        assertEquals("Unexpected node state", State.ERRORED, node.getState());
+    }
+
+    public void testOpenSucceeds() throws Exception
+    {
+        String nodeName = getTestName();
+        Map<String, Object> attributes = Collections.<String, Object>singletonMap(TestVirtualHostNode.NAME, nodeName);
+
+        final AtomicBoolean onFailureFlag = new AtomicBoolean();
+        DurableConfigurationStore store = mock(DurableConfigurationStore.class);
+        AbstractVirtualHostNode node = new TestAbstractVirtualHostNode( _broker, attributes, store)
+        {
+            @Override
+            public void onValidate()
+            {
+                // no op
+            }
+
+            @Override
+            protected void onExceptionInOpen(RuntimeException e)
+            {
+                try
+                {
+                    super.onExceptionInOpen(e);
+                }
+                finally
+                {
+                    onFailureFlag.set(true);
+                }
+            }
+        };
+
+        node.open();
+        assertEquals("Unexpected node state", State.ACTIVE, node.getState());
+        assertFalse("onExceptionInOpen was called", onFailureFlag.get());
+    }
+
+
+    public void testDeleteInErrorStateAfterOpen()
+    {
+        String nodeName = getTestName();
+        Map<String, Object> attributes = Collections.<String, Object>singletonMap(TestVirtualHostNode.NAME, nodeName);
+
+        final DurableConfigurationStore store = mock(DurableConfigurationStore.class);
+        doThrow(new RuntimeException("Cannot open store")).when(store).openConfigurationStore(any(ConfiguredObject.class), any(boolean.class));
+        AbstractStandardVirtualHostNode node = createAbstractStandardVirtualHostNode(attributes, store);
+        node.open();
+        assertEquals("Unexpected node state", State.ERRORED, node.getState());
+
+        node.delete();
+        assertEquals("Unexpected state", State.DELETED, node.getState());
+    }
+
+    public void testActivateInErrorStateAfterOpen() throws Exception
+    {
+        String nodeName = getTestName();
+        Map<String, Object> attributes = Collections.<String, Object>singletonMap(TestVirtualHostNode.NAME, nodeName);
+
+        DurableConfigurationStore store = mock(DurableConfigurationStore.class);
+        doThrow(new RuntimeException("Cannot open store")).when(store).openConfigurationStore(any(ConfiguredObject.class), any(boolean.class));
+        AbstractVirtualHostNode node = createAbstractStandardVirtualHostNode(attributes, store);
+        node.open();
+        assertEquals("Unexpected node state", State.ERRORED, node.getState());
+        doNothing().when(store).openConfigurationStore(any(ConfiguredObject.class), any(boolean.class));
+
+        node.setAttributes(Collections.<String, Object>singletonMap(VirtualHostNode.DESIRED_STATE, State.ACTIVE));
+        assertEquals("Unexpected state", State.ACTIVE, node.getState());
+    }
+
+    public void testStartInErrorStateAfterOpen() throws Exception
+    {
+        String nodeName = getTestName();
+        Map<String, Object> attributes = Collections.<String, Object>singletonMap(TestVirtualHostNode.NAME, nodeName);
+
+        DurableConfigurationStore store = mock(DurableConfigurationStore.class);
+        doThrow(new RuntimeException("Cannot open store")).when(store).openConfigurationStore(any(ConfiguredObject.class), any(boolean.class));
+        AbstractVirtualHostNode node = createAbstractStandardVirtualHostNode(attributes, store);
+        node.open();
+        assertEquals("Unexpected node state", State.ERRORED, node.getState());
+        doNothing().when(store).openConfigurationStore(any(ConfiguredObject.class), any(boolean.class));
+
+        node.start();
+        assertEquals("Unexpected state", State.ACTIVE, node.getState());
+    }
+
     private ConfiguredObjectRecord createVirtualHostConfiguredObjectRecord(UUID virtualHostId)
     {
         Map<String, Object> virtualHostAttributes = new HashMap<>();
@@ -384,4 +518,62 @@
         return configStoreThatProduces(null);
     }
 
+
+    private AbstractStandardVirtualHostNode createAbstractStandardVirtualHostNode(final Map<String, Object> attributes, final DurableConfigurationStore store)
+    {
+        return new AbstractStandardVirtualHostNode(attributes,  _broker){
+
+            @Override
+            protected void writeLocationEventLog()
+            {
+
+            }
+
+            @Override
+            protected DurableConfigurationStore createConfigurationStore()
+            {
+                return store;
+            }
+        };
+    }
+
+    private class TestAbstractVirtualHostNode extends AbstractVirtualHostNode
+    {
+        private DurableConfigurationStore _store;
+
+        public TestAbstractVirtualHostNode(Broker parent, Map attributes, DurableConfigurationStore store)
+        {
+            super(parent, attributes);
+            _store = store;
+        }
+
+        @Override
+        public void onValidate()
+        {
+            throw new RuntimeException("Cannot validate");
+        }
+
+        @Override
+        protected DurableConfigurationStore createConfigurationStore()
+        {
+            return _store;
+        }
+
+        @Override
+        protected void activate()
+        {
+        }
+
+        @Override
+        protected ConfiguredObjectRecord enrichInitialVirtualHostRootRecord(ConfiguredObjectRecord vhostRecord)
+        {
+            return null;
+        }
+
+        @Override
+        public Collection<? extends RemoteReplicationNode> getRemoteReplicationNodes()
+        {
+            return null;
+        }
+    }
 }
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/TestVirtualHostNode.java b/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/TestVirtualHostNode.java
index 277ef8b..4fe8136 100644
--- a/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/TestVirtualHostNode.java
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/TestVirtualHostNode.java
@@ -53,6 +53,12 @@
     }
 
     @Override
+    public DurableConfigurationStore getConfigurationStore()
+    {
+        return _store;
+    }
+
+    @Override
     protected void writeLocationEventLog()
     {
     }
diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImpl.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImpl.java
index f0edc59..1adc656 100644
--- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImpl.java
+++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImpl.java
@@ -25,10 +25,10 @@
 import java.util.Collections;
 import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.atomic.AtomicReference;
 
 import org.apache.log4j.Logger;
 
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
 import org.apache.qpid.server.model.AbstractConfiguredObject;
 import org.apache.qpid.server.model.AccessControlProvider;
 import org.apache.qpid.server.model.Broker;
@@ -83,6 +83,29 @@
     }
 
     @Override
+    protected void validateOnCreate()
+    {
+        DefaultAccessControl accessControl = null;
+        try
+        {
+            accessControl = new DefaultAccessControl(getPath(), _broker);
+            accessControl.validate();
+            accessControl.open();
+        }
+        catch(RuntimeException e)
+        {
+            throw new IllegalConfigurationException(e.getMessage(), e);
+        }
+        finally
+        {
+            if (accessControl != null)
+            {
+                accessControl.close();
+            }
+        }
+    }
+
+    @Override
     protected void onOpen()
     {
         super.onOpen();
@@ -105,6 +128,7 @@
     @StateTransition(currentState = {State.UNINITIALIZED, State.QUIESCED, State.ERRORED}, desiredState = State.ACTIVE)
     private void activate()
     {
+
         if(_broker.isManagementMode())
         {
 
@@ -136,7 +160,10 @@
     protected void onClose()
     {
         super.onClose();
-        _accessControl.close();
+        if (_accessControl != null)
+        {
+            _accessControl.close();
+        }
     }
 
     @StateTransition(currentState = State.UNINITIALIZED, desiredState = State.QUIESCED)
diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImplTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImplTest.java
new file mode 100644
index 0000000..005d2a9
--- /dev/null
+++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImplTest.java
@@ -0,0 +1,80 @@
+/*
+ *
+ * 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.server.security.access.plugins;
+
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
+import org.apache.qpid.server.configuration.updater.TaskExecutor;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.Model;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class ACLFileAccessControlProviderImplTest extends QpidTestCase
+{
+    private TaskExecutor _taskExecutor;
+    private Model _model;
+    private Broker _broker;
+
+    public void setUp() throws Exception
+    {
+        super.setUp();
+        _taskExecutor = CurrentThreadTaskExecutor.newStartedInstance();
+        _model = BrokerModel.getInstance();
+
+        _broker = mock(Broker.class);
+        when(_broker.getTaskExecutor()).thenReturn(_taskExecutor);
+        when(_broker.getModel()).thenReturn(_model);
+        when(_broker.getId()).thenReturn(UUID.randomUUID());
+    }
+
+    public void testValidationOnCreateWithNonExistingACLFile()
+    {
+        Map<String,Object> attributes = new HashMap<>();
+        String aclFilePath = new File(TMP_FOLDER, "test_" + getTestName() + System.nanoTime() + ".acl").getAbsolutePath();
+
+        attributes.put("path", aclFilePath);
+        attributes.put(ACLFileAccessControlProvider.NAME, getTestName());
+
+
+        ACLFileAccessControlProviderImpl aclProvider = new ACLFileAccessControlProviderImpl(attributes, _broker);
+        try
+        {
+            aclProvider.create();
+            fail("Exception is expected on validation with non-existing ACL file");
+        }
+        catch (IllegalConfigurationException e)
+        {
+            assertEquals("Unexpected exception message:" + e.getMessage(), String.format("ACL file '%s' is not found", aclFilePath ), e.getMessage());
+        }
+    }
+
+}
diff --git a/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java b/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java
index 79f73b5..7574cc3 100644
--- a/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java
+++ b/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java
@@ -1322,6 +1322,12 @@
         return _subject;
     }
 
+    public ChannelMethodProcessor getMethodProcessor()
+    {
+        // TODO
+        return null;
+    }
+
 
     private class ImmediateAction implements Action<MessageInstance>
     {
diff --git a/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ChannelMethodProcessor.java b/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ChannelMethodProcessor.java
new file mode 100644
index 0000000..d8c7115
--- /dev/null
+++ b/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ChannelMethodProcessor.java
@@ -0,0 +1,25 @@
+/*
+ *
+ * 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.server.protocol.v0_8;
+
+public interface ChannelMethodProcessor
+{
+}
diff --git a/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ServerMethodDispatcherImpl.java b/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ServerMethodDispatcherImpl.java
index d830070..6f4c1d9 100644
--- a/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ServerMethodDispatcherImpl.java
+++ b/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ServerMethodDispatcherImpl.java
@@ -1,2237 +1,2266 @@
-/*

- *

- * 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.server.protocol.v0_8;

-

-import java.security.AccessControlException;

-import java.util.Collection;

-import java.util.EnumSet;

-import java.util.HashMap;

-import java.util.HashSet;

-import java.util.Map;

-import java.util.UUID;

-

-import javax.security.sasl.SaslException;

-import javax.security.sasl.SaslServer;

-

-import org.apache.log4j.Logger;

-

-import org.apache.qpid.AMQConnectionException;

-import org.apache.qpid.AMQException;

-import org.apache.qpid.exchange.ExchangeDefaults;

-import org.apache.qpid.framing.*;

-import org.apache.qpid.protocol.AMQConstant;

-import org.apache.qpid.server.consumer.ConsumerImpl;

-import org.apache.qpid.server.exchange.ExchangeImpl;

-import org.apache.qpid.server.filter.AMQInvalidArgumentException;

-import org.apache.qpid.server.flow.FlowCreditManager;

-import org.apache.qpid.server.flow.MessageOnlyCreditManager;

-import org.apache.qpid.server.message.InstanceProperties;

-import org.apache.qpid.server.message.MessageDestination;

-import org.apache.qpid.server.message.MessageInstance;

-import org.apache.qpid.server.message.MessageSource;

-import org.apache.qpid.server.message.ServerMessage;

-import org.apache.qpid.server.model.Broker;

-import org.apache.qpid.server.model.ExclusivityPolicy;

-import org.apache.qpid.server.model.LifetimePolicy;

-import org.apache.qpid.server.model.NoFactoryForTypeException;

-import org.apache.qpid.server.model.Queue;

-import org.apache.qpid.server.model.State;

-import org.apache.qpid.server.model.UnknownConfiguredObjectException;

-import org.apache.qpid.server.model.port.AmqpPort;

-import org.apache.qpid.server.protocol.AMQSessionModel;

-import org.apache.qpid.server.queue.AMQQueue;

-import org.apache.qpid.server.queue.QueueArgumentsConverter;

-import org.apache.qpid.server.security.SubjectCreator;

-import org.apache.qpid.server.security.auth.SubjectAuthenticationResult;

-import org.apache.qpid.server.virtualhost.ExchangeExistsException;

-import org.apache.qpid.server.virtualhost.ExchangeIsAlternateException;

-import org.apache.qpid.server.virtualhost.QueueExistsException;

-import org.apache.qpid.server.virtualhost.RequiredExchangeException;

-import org.apache.qpid.server.virtualhost.ReservedExchangeNameException;

-import org.apache.qpid.server.virtualhost.VirtualHostImpl;

-

-public class ServerMethodDispatcherImpl implements MethodDispatcher

-{

-    private static final Logger _logger = Logger.getLogger(ServerMethodDispatcherImpl.class);

-

-    private final AMQProtocolSession<?> _connection;

-

-

-    public static MethodDispatcher createMethodDispatcher(AMQProtocolSession<?> connection)

-    {

-        return new ServerMethodDispatcherImpl(connection);

-    }

-

-

-    public ServerMethodDispatcherImpl(AMQProtocolSession<?> connection)

-    {

-        _connection = connection;

-    }

-

-

-    protected final AMQProtocolSession<?> getConnection()

-    {

-        return _connection;

-    }

-

-    public boolean dispatchAccessRequest(AccessRequestBody body, int channelId) throws AMQException

-    {

-        final AMQChannel channel = _connection.getChannel(channelId);

-        if (channel == null)

-        {

-            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());

-        }

-

-        MethodRegistry methodRegistry = _connection.getMethodRegistry();

-

-        if(ProtocolVersion.v0_91.equals(_connection.getProtocolVersion()) )

-        {

-            throw new AMQException(AMQConstant.COMMAND_INVALID, "AccessRequest not present in AMQP versions other than 0-8, 0-9");

-        }

-

-        // We don't implement access control class, but to keep clients happy that expect it

-        // always use the "0" ticket.

-        AccessRequestOkBody response = methodRegistry.createAccessRequestOkBody(0);

-        channel.sync();

-        _connection.writeFrame(response.generateFrame(channelId));

-        return true;

-    }

-

-    public boolean dispatchBasicAck(BasicAckBody body, int channelId) throws AMQException

-    {

-

-        if (_logger.isDebugEnabled())

-        {

-            _logger.debug("Ack(Tag:" + body.getDeliveryTag() + ":Mult:" + body.getMultiple() + ") received on channel " + channelId);

-        }

-

-        final AMQChannel channel = _connection.getChannel(channelId);

-

-        if (channel == null)

-        {

-            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());

-        }

-

-        // this method throws an AMQException if the delivery tag is not known

-        channel.acknowledgeMessage(body.getDeliveryTag(), body.getMultiple());

-        return true;

-    }

-

-    public boolean dispatchBasicCancel(BasicCancelBody body, int channelId) throws AMQException

-    {

-        final AMQChannel channel = _connection.getChannel(channelId);

-

-

-        if (channel == null)

-        {

-            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());

-        }

-

-        if (_logger.isDebugEnabled())

-        {

-            _logger.debug("BasicCancel: for:" + body.getConsumerTag() +

-                       " nowait:" + body.getNowait());

-        }

-

-        channel.unsubscribeConsumer(body.getConsumerTag());

-        if (!body.getNowait())

-        {

-            MethodRegistry methodRegistry = _connection.getMethodRegistry();

-            BasicCancelOkBody cancelOkBody = methodRegistry.createBasicCancelOkBody(body.getConsumerTag());

-            channel.sync();

-            _connection.writeFrame(cancelOkBody.generateFrame(channelId));

-        }

-        return true;

-    }

-

-    public boolean dispatchBasicConsume(BasicConsumeBody body, int channelId) throws AMQException

-    {

-        AMQChannel channel = _connection.getChannel(channelId);

-        VirtualHostImpl<?,?,?> vHost = _connection.getVirtualHost();

-

-        if (channel == null)

-        {

-            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());

-        }

-        else

-        {

-            channel.sync();

-            String queueName = body.getQueue() == null ? null : body.getQueue().asString();

-            if (_logger.isDebugEnabled())

-            {

-                _logger.debug("BasicConsume: from '" + queueName +

-                              "' for:" + body.getConsumerTag() +

-                              " nowait:" + body.getNowait() +

-                              " args:" + body.getArguments());

-            }

-

-            MessageSource queue = queueName == null ? channel.getDefaultQueue() : vHost.getQueue(queueName);

-            final Collection<MessageSource> sources = new HashSet<>();

-            if(queue != null)

-            {

-                sources.add(queue);

-            }

-            else if(vHost.getContextValue(Boolean.class, "qpid.enableMultiQueueConsumers")

-                    && body.getArguments() != null

-                    && body.getArguments().get("x-multiqueue") instanceof Collection)

-            {

-                for(Object object : (Collection<Object>) body.getArguments().get("x-multiqueue"))

-                {

-                    String sourceName = String.valueOf(object);

-                    sourceName = sourceName.trim();

-                    if(sourceName.length() != 0)

-                    {

-                        MessageSource source = vHost.getMessageSource(sourceName);

-                        if(source == null)

-                        {

-                            sources.clear();

-                            break;

-                        }

-                        else

-                        {

-                            sources.add(source);

-                        }

-                    }

-                }

-                queueName = body.getArguments().get("x-multiqueue").toString();

-            }

-

-            if (sources.isEmpty())

-            {

-                if (_logger.isDebugEnabled())

-                {

-                    _logger.debug("No queue for '" + queueName + "'");

-                }

-                if (queueName != null)

-                {

-                    String msg = "No such queue, '" + queueName + "'";

-                    throw body.getChannelException(AMQConstant.NOT_FOUND, msg, _connection.getMethodRegistry());

-                }

-                else

-                {

-                    String msg = "No queue name provided, no default queue defined.";

-                    throw body.getConnectionException(AMQConstant.NOT_ALLOWED, msg, _connection.getMethodRegistry());

-                }

-            }

-            else

-            {

-                final AMQShortString consumerTagName;

-

-                if (body.getConsumerTag() != null)

-                {

-                    consumerTagName = body.getConsumerTag().intern(false);

-                }

-                else

-                {

-                    consumerTagName = null;

-                }

-

-                try

-                {

-                    if(consumerTagName == null || channel.getSubscription(consumerTagName) == null)

-                    {

-

-                        AMQShortString consumerTag = channel.consumeFromSource(consumerTagName,

-                                                                               sources,

-                                                                               !body.getNoAck(),

-                                                                               body.getArguments(),

-                                                                               body.getExclusive(),

-                                                                               body.getNoLocal());

-                        if (!body.getNowait())

-                        {

-                            MethodRegistry methodRegistry = _connection.getMethodRegistry();

-                            AMQMethodBody responseBody = methodRegistry.createBasicConsumeOkBody(consumerTag);

-                            _connection.writeFrame(responseBody.generateFrame(channelId));

-

-                        }

-                    }

-                    else

-                    {

-                        AMQShortString msg = AMQShortString.validValueOf("Non-unique consumer tag, '" + body.getConsumerTag() + "'");

-

-                        MethodRegistry methodRegistry = _connection.getMethodRegistry();

-                        AMQMethodBody responseBody = methodRegistry.createConnectionCloseBody(AMQConstant.NOT_ALLOWED.getCode(),    // replyCode

-                                                                 msg,               // replytext

-                                                                 body.getClazz(),

-                                                                 body.getMethod());

-                        _connection.writeFrame(responseBody.generateFrame(0));

-                    }

-

-                }

-                catch (AMQInvalidArgumentException ise)

-                {

-                    _logger.debug("Closing connection due to invalid selector");

-

-                    MethodRegistry methodRegistry = _connection.getMethodRegistry();

-                    AMQMethodBody responseBody = methodRegistry.createChannelCloseBody(AMQConstant.ARGUMENT_INVALID.getCode(),

-                                                                                       AMQShortString.validValueOf(ise.getMessage()),

-                                                                                       body.getClazz(),

-                                                                                       body.getMethod());

-                    _connection.writeFrame(responseBody.generateFrame(channelId));

-

-

-                }

-                catch (AMQQueue.ExistingExclusiveConsumer e)

-                {

-                    throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,

-                                                      "Cannot subscribe to queue "

-                                                      + queue.getName()

-                                                      + " as it already has an existing exclusive consumer",

-                                                      _connection.getMethodRegistry());

-                }

-                catch (AMQQueue.ExistingConsumerPreventsExclusive e)

-                {

-                    throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,

-                                                      "Cannot subscribe to queue "

-                                                      + queue.getName()

-                                                      + " exclusively as it already has a consumer",

-                                                      _connection.getMethodRegistry());

-                }

-                catch (AccessControlException e)

-                {

-                    throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,

-                                                      "Cannot subscribe to queue "

-                                                      + queue.getName()

-                                                      + " permission denied", _connection.getMethodRegistry());

-                }

-                catch (MessageSource.ConsumerAccessRefused consumerAccessRefused)

-                {

-                    throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,

-                                                      "Cannot subscribe to queue "

-                                                      + queue.getName()

-                                                      + " as it already has an incompatible exclusivity policy",

-                                                      _connection.getMethodRegistry());

-                }

-

-            }

-        }

-        return true;

-    }

-

-    public boolean dispatchBasicGet(BasicGetBody body, int channelId) throws AMQException

-    {

-

-        VirtualHostImpl vHost = _connection.getVirtualHost();

-

-        AMQChannel channel = _connection.getChannel(channelId);

-        if (channel == null)

-        {

-            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());

-        }

-        else

-        {

-            channel.sync();

-            AMQQueue queue = body.getQueue() == null ? channel.getDefaultQueue() : vHost.getQueue(body.getQueue().toString());

-            if (queue == null)

-            {

-                _logger.info("No queue for '" + body.getQueue() + "'");

-                if(body.getQueue()!=null)

-                {

-                    throw body.getConnectionException(AMQConstant.NOT_FOUND,

-                                                      "No such queue, '" + body.getQueue() + "'",

-                                                      _connection.getMethodRegistry());

-                }

-                else

-                {

-                    throw body.getConnectionException(AMQConstant.NOT_ALLOWED,

-                                                      "No queue name provided, no default queue defined.",

-                                                      _connection.getMethodRegistry());

-                }

-            }

-            else

-            {

-

-                try

-                {

-                    if (!performGet(queue, _connection, channel, !body.getNoAck()))

-                    {

-                        MethodRegistry methodRegistry = _connection.getMethodRegistry();

-

-                        BasicGetEmptyBody responseBody = methodRegistry.createBasicGetEmptyBody(null);

-

-

-                        _connection.writeFrame(responseBody.generateFrame(channelId));

-                    }

-                }

-                catch (AccessControlException e)

-                {

-                    throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,

-                                                      e.getMessage(), _connection.getMethodRegistry());

-                }

-                catch (MessageSource.ExistingExclusiveConsumer e)

-                {

-                    throw body.getConnectionException(AMQConstant.NOT_ALLOWED,

-                                                      "Queue has an exclusive consumer",

-                                                      _connection.getMethodRegistry());

-                }

-                catch (MessageSource.ExistingConsumerPreventsExclusive e)

-                {

-                    throw body.getConnectionException(AMQConstant.INTERNAL_ERROR,

-                                                      "The GET request has been evaluated as an exclusive consumer, " +

-                                                      "this is likely due to a programming error in the Qpid broker",

-                                                      _connection.getMethodRegistry());

-                }

-                catch (MessageSource.ConsumerAccessRefused consumerAccessRefused)

-                {

-                    throw body.getConnectionException(AMQConstant.NOT_ALLOWED,

-                                                      "Queue has an incompatible exclusivit policy",

-                                                      _connection.getMethodRegistry());

-                }

-            }

-        }

-        return true;

-    }

-

-    public static boolean performGet(final AMQQueue queue,

-                                     final AMQProtocolSession session,

-                                     final AMQChannel channel,

-                                     final boolean acks)

-            throws AMQException, MessageSource.ExistingConsumerPreventsExclusive,

-                   MessageSource.ExistingExclusiveConsumer, MessageSource.ConsumerAccessRefused

-    {

-

-        final FlowCreditManager singleMessageCredit = new MessageOnlyCreditManager(1L);

-

-        final GetDeliveryMethod getDeliveryMethod =

-                new GetDeliveryMethod(singleMessageCredit, session, channel, queue);

-        final RecordDeliveryMethod getRecordMethod = new RecordDeliveryMethod()

-        {

-

-            public void recordMessageDelivery(final ConsumerImpl sub, final MessageInstance entry, final long deliveryTag)

-            {

-                channel.addUnacknowledgedMessage(entry, deliveryTag, null);

-            }

-        };

-

-        ConsumerTarget_0_8 target;

-        EnumSet<ConsumerImpl.Option> options = EnumSet.of(ConsumerImpl.Option.TRANSIENT, ConsumerImpl.Option.ACQUIRES,

-                                                          ConsumerImpl.Option.SEES_REQUEUES);

-        if(acks)

-        {

-

-            target = ConsumerTarget_0_8.createAckTarget(channel,

-                                                        AMQShortString.EMPTY_STRING, null,

-                                                        singleMessageCredit, getDeliveryMethod, getRecordMethod);

-        }

-        else

-        {

-            target = ConsumerTarget_0_8.createGetNoAckTarget(channel,

-                                                             AMQShortString.EMPTY_STRING, null,

-                                                             singleMessageCredit, getDeliveryMethod, getRecordMethod);

-        }

-

-        ConsumerImpl sub = queue.addConsumer(target, null, AMQMessage.class, "", options);

-        sub.flush();

-        sub.close();

-        return(getDeliveryMethod.hasDeliveredMessage());

-

-

-    }

-

-

-    private static class GetDeliveryMethod implements ClientDeliveryMethod

-    {

-

-        private final FlowCreditManager _singleMessageCredit;

-        private final AMQProtocolSession _session;

-        private final AMQChannel _channel;

-        private final AMQQueue _queue;

-        private boolean _deliveredMessage;

-

-        public GetDeliveryMethod(final FlowCreditManager singleMessageCredit,

-                                 final AMQProtocolSession session,

-                                 final AMQChannel channel, final AMQQueue queue)

-        {

-            _singleMessageCredit = singleMessageCredit;

-            _session = session;

-            _channel = channel;

-            _queue = queue;

-        }

-

-        @Override

-        public long deliverToClient(final ConsumerImpl sub, final ServerMessage message,

-                                    final InstanceProperties props, final long deliveryTag)

-        {

-            _singleMessageCredit.useCreditForMessage(message.getSize());

-            long size =_session.getProtocolOutputConverter().writeGetOk(message,

-                                                                        props,

-                                                                        _channel.getChannelId(),

-                                                                        deliveryTag,

-                                                                        _queue.getQueueDepthMessages());

-

-            _deliveredMessage = true;

-            return size;

-        }

-

-        public boolean hasDeliveredMessage()

-        {

-            return _deliveredMessage;

-        }

-    }

-

-    public boolean dispatchBasicPublish(BasicPublishBody body, int channelId) throws AMQException

-    {

-        if (_logger.isDebugEnabled())

-        {

-            _logger.debug("Publish received on channel " + channelId);

-        }

-

-        AMQShortString exchangeName = body.getExchange();

-        VirtualHostImpl vHost = _connection.getVirtualHost();

-

-        // TODO: check the delivery tag field details - is it unique across the broker or per subscriber?

-

-        MessageDestination destination;

-

-        if (exchangeName == null || AMQShortString.EMPTY_STRING.equals(exchangeName))

-        {

-            destination = vHost.getDefaultDestination();

-        }

-        else

-        {

-            destination = vHost.getMessageDestination(exchangeName.toString());

-        }

-

-        // if the exchange does not exist we raise a channel exception

-        if (destination == null)

-        {

-            throw body.getChannelException(AMQConstant.NOT_FOUND, "Unknown exchange name",

-                                           _connection.getMethodRegistry());

-        }

-        else

-        {

-            // The partially populated BasicDeliver frame plus the received route body

-            // is stored in the channel. Once the final body frame has been received

-            // it is routed to the exchange.

-            AMQChannel channel = _connection.getChannel(channelId);

-

-            if (channel == null)

-            {

-                throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());

-            }

-

-            MessagePublishInfo info = new MessagePublishInfo(body.getExchange(),

-                                                             body.getImmediate(),

-                                                             body.getMandatory(),

-                                                             body.getRoutingKey());

-            info.setExchange(exchangeName);

-            try

-            {

-                channel.setPublishFrame(info, destination);

-            }

-            catch (AccessControlException e)

-            {

-                throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,

-                                                  e.getMessage(),

-                                                  _connection.getMethodRegistry());

-            }

-        }

-        return true;

-    }

-

-    public boolean dispatchBasicQos(BasicQosBody body, int channelId) throws AMQException

-    {

-        AMQChannel channel = _connection.getChannel(channelId);

-        if (channel == null)

-        {

-            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());

-        }

-        channel.sync();

-        channel.setCredit(body.getPrefetchSize(), body.getPrefetchCount());

-

-

-        MethodRegistry methodRegistry = _connection.getMethodRegistry();

-        AMQMethodBody responseBody = methodRegistry.createBasicQosOkBody();

-        _connection.writeFrame(responseBody.generateFrame(channelId));

-

-        return true;

-    }

-

-    public boolean dispatchBasicRecover(BasicRecoverBody body, int channelId) throws AMQException

-    {

-        _logger.debug("Recover received on protocol session " + _connection

-                                                + " and channel " + channelId);

-        AMQChannel channel = _connection.getChannel(channelId);

-

-

-        if (channel == null)

-        {

-            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());

-        }

-

-        channel.resend();

-

-        // Qpid 0-8 hacks a synchronous -ok onto recover.

-        // In Qpid 0-9 we create a separate sync-recover, sync-recover-ok pair to be "more" compliant

-        if(_connection.getProtocolVersion().equals(ProtocolVersion.v8_0))

-        {

-            MethodRegistry methodRegistry = _connection.getMethodRegistry();

-            AMQMethodBody recoverOk = methodRegistry.createBasicRecoverSyncOkBody();

-            channel.sync();

-            _connection.writeFrame(recoverOk.generateFrame(channelId));

-

-        }

-

-        return true;

-    }

-

-    public boolean dispatchBasicReject(BasicRejectBody body, int channelId) throws AMQException

-    {

-

-        AMQChannel channel = _connection.getChannel(channelId);

-

-        if (channel == null)

-        {

-            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());

-        }

-

-        if (_logger.isDebugEnabled())

-        {

-            _logger.debug("Rejecting:" + body.getDeliveryTag() +

-                          ": Requeue:" + body.getRequeue() +

-                          " on channel:" + channel.debugIdentity());

-        }

-

-        long deliveryTag = body.getDeliveryTag();

-

-        MessageInstance message = channel.getUnacknowledgedMessageMap().get(deliveryTag);

-

-        if (message == null)

-        {

-            _logger.warn("Dropping reject request as message is null for tag:" + deliveryTag);

-        }

-        else

-        {

-

-            if (message.getMessage() == null)

-            {

-                _logger.warn("Message has already been purged, unable to Reject.");

-            }

-            else

-            {

-

-                if (_logger.isDebugEnabled())

-                {

-                    _logger.debug("Rejecting: DT:" + deliveryTag + "-" + message.getMessage() +

-                                  ": Requeue:" + body.getRequeue() +

-                                  " on channel:" + channel.debugIdentity());

-                }

-

-                if (body.getRequeue())

-                {

-                    //this requeue represents a message rejected from the pre-dispatch queue

-                    //therefore we need to amend the delivery counter.

-                    message.decrementDeliveryCount();

-

-                    channel.requeue(deliveryTag);

-                }

-                else

-                {

-                    // Since the Java client abuses the reject flag for requeing after rollback, we won't set reject here

-                    // as it would prevent redelivery

-                    // message.reject();

-

-                    final boolean maxDeliveryCountEnabled = channel.isMaxDeliveryCountEnabled(deliveryTag);

-                    _logger.debug("maxDeliveryCountEnabled: "

-                                  + maxDeliveryCountEnabled

-                                  + " deliveryTag "

-                                  + deliveryTag);

-                    if (maxDeliveryCountEnabled)

-                    {

-                        final boolean deliveredTooManyTimes = channel.isDeliveredTooManyTimes(deliveryTag);

-                        _logger.debug("deliveredTooManyTimes: "

-                                      + deliveredTooManyTimes

-                                      + " deliveryTag "

-                                      + deliveryTag);

-                        if (deliveredTooManyTimes)

-                        {

-                            channel.deadLetter(body.getDeliveryTag());

-                        }

-                        else

-                        {

-                            //this requeue represents a message rejected because of a recover/rollback that we

-                            //are not ready to DLQ. We rely on the reject command to resend from the unacked map

-                            //and therefore need to increment the delivery counter so we cancel out the effect

-                            //of the AMQChannel#resend() decrement.

-                            message.incrementDeliveryCount();

-                        }

-                    }

-                    else

-                    {

-                        channel.requeue(deliveryTag);

-                    }

-                }

-            }

-        }

-        return true;

-    }

-

-    public boolean dispatchChannelOpen(ChannelOpenBody body, int channelId) throws AMQException

-    {

-        VirtualHostImpl virtualHost = _connection.getVirtualHost();

-

-        // Protect the broker against out of order frame request.

-        if (virtualHost == null)

-        {

-            throw new AMQException(AMQConstant.COMMAND_INVALID, "Virtualhost has not yet been set. ConnectionOpen has not been called.", null);

-        }

-        _logger.info("Connecting to: " + virtualHost.getName());

-

-        final AMQChannel channel = new AMQChannel(_connection, channelId, virtualHost.getMessageStore());

-

-        _connection.addChannel(channel);

-

-        ChannelOpenOkBody response;

-

-

-        response = _connection.getMethodRegistry().createChannelOpenOkBody();

-

-

-        _connection.writeFrame(response.generateFrame(channelId));

-        return true;

-    }

-

-

-    public boolean dispatchAccessRequestOk(AccessRequestOkBody body, int channelId) throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-

-    public boolean dispatchBasicCancelOk(BasicCancelOkBody body, int channelId) throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-    public boolean dispatchBasicConsumeOk(BasicConsumeOkBody body, int channelId) throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-    public boolean dispatchBasicDeliver(BasicDeliverBody body, int channelId) throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-    public boolean dispatchBasicGetEmpty(BasicGetEmptyBody body, int channelId) throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-    public boolean dispatchBasicGetOk(BasicGetOkBody body, int channelId) throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-    public boolean dispatchBasicQosOk(BasicQosOkBody body, int channelId) throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-    public boolean dispatchBasicReturn(BasicReturnBody body, int channelId) throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-    public boolean dispatchChannelClose(ChannelCloseBody body, int channelId) throws AMQException

-    {

-

-        if (_logger.isInfoEnabled())

-        {

-            _logger.info("Received channel close for id " + channelId

-                                             + " citing class " + body.getClassId() +

-                         " and method " + body.getMethodId());

-        }

-

-

-        AMQChannel channel = _connection.getChannel(channelId);

-

-        if (channel == null)

-        {

-            throw body.getConnectionException(AMQConstant.CHANNEL_ERROR,

-                                              "Trying to close unknown channel",

-                                              _connection.getMethodRegistry());

-        }

-        channel.sync();

-        _connection.closeChannel(channelId);

-        // Client requested closure so we don't wait for ok we send it

-        _connection.closeChannelOk(channelId);

-

-        MethodRegistry methodRegistry = _connection.getMethodRegistry();

-        ChannelCloseOkBody responseBody = methodRegistry.createChannelCloseOkBody();

-        _connection.writeFrame(responseBody.generateFrame(channelId));

-        return true;

-    }

-

-

-    public boolean dispatchChannelCloseOk(ChannelCloseOkBody body, int channelId) throws AMQException

-    {

-

-        _logger.info("Received channel-close-ok for channel-id " + channelId);

-

-        // Let the Protocol Session know the channel is now closed.

-        _connection.closeChannelOk(channelId);

-        return true;

-    }

-

-

-    public boolean dispatchChannelFlow(ChannelFlowBody body, int channelId) throws AMQException

-    {

-        final AMQProtocolSession<?> connection = getConnection();

-

-

-        AMQChannel channel = connection.getChannel(channelId);

-

-        if (channel == null)

-        {

-            throw body.getChannelNotFoundException(channelId, connection.getMethodRegistry());

-        }

-        channel.sync();

-        channel.setSuspended(!body.getActive());

-        _logger.debug("Channel.Flow for channel " + channelId + ", active=" + body.getActive());

-

-        MethodRegistry methodRegistry = connection.getMethodRegistry();

-        AMQMethodBody responseBody = methodRegistry.createChannelFlowOkBody(body.getActive());

-        connection.writeFrame(responseBody.generateFrame(channelId));

-        return true;

-    }

-

-    public boolean dispatchChannelFlowOk(ChannelFlowOkBody body, int channelId) throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-    public boolean dispatchChannelOpenOk(ChannelOpenOkBody body, int channelId) throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-

-    public boolean dispatchConnectionOpen(ConnectionOpenBody body, int channelId) throws AMQException

-    {

-

-        //ignore leading '/'

-        String virtualHostName;

-        if ((body.getVirtualHost() != null) && body.getVirtualHost().charAt(0) == '/')

-        {

-            virtualHostName = new StringBuilder(body.getVirtualHost().subSequence(1, body.getVirtualHost().length())).toString();

-        }

-        else

-        {

-            virtualHostName = body.getVirtualHost() == null ? null : String.valueOf(body.getVirtualHost());

-        }

-

-        VirtualHostImpl virtualHost = ((AmqpPort) _connection.getPort()).getVirtualHost(virtualHostName);

-

-        if (virtualHost == null)

-        {

-            throw body.getConnectionException(AMQConstant.NOT_FOUND, "Unknown virtual host: '" + virtualHostName + "'",

-                                              _connection.getMethodRegistry());

-        }

-        else

-        {

-            // Check virtualhost access

-            if (virtualHost.getState() != State.ACTIVE)

-            {

-                throw body.getConnectionException(AMQConstant.CONNECTION_FORCED,

-                                                  "Virtual host '" + virtualHost.getName() + "' is not active",

-                                                  _connection.getMethodRegistry());

-            }

-

-            _connection.setVirtualHost(virtualHost);

-            try

-            {

-                virtualHost.getSecurityManager().authoriseCreateConnection(_connection);

-            }

-            catch (AccessControlException e)

-            {

-                throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,

-                                                  e.getMessage(),

-                                                  _connection.getMethodRegistry());

-            }

-

-            // See Spec (0.8.2). Section  3.1.2 Virtual Hosts

-            if (_connection.getContextKey() == null)

-            {

-                _connection.setContextKey(new AMQShortString(Long.toString(System.currentTimeMillis())));

-            }

-

-            MethodRegistry methodRegistry = _connection.getMethodRegistry();

-            AMQMethodBody responseBody =  methodRegistry.createConnectionOpenOkBody(body.getVirtualHost());

-

-            _connection.writeFrame(responseBody.generateFrame(channelId));

-        }

-        return true;

-    }

-

-

-    public boolean dispatchConnectionClose(ConnectionCloseBody body, int channelId) throws AMQException

-    {

-        if (_logger.isInfoEnabled())

-        {

-            _logger.info("ConnectionClose received with reply code/reply text " + body.getReplyCode() + "/" +

-                         body.getReplyText() + " for " + _connection);

-        }

-        try

-        {

-            _connection.closeSession();

-        }

-        catch (Exception e)

-        {

-            _logger.error("Error closing protocol session: " + e, e);

-        }

-

-        MethodRegistry methodRegistry = _connection.getMethodRegistry();

-        ConnectionCloseOkBody responseBody = methodRegistry.createConnectionCloseOkBody();

-        _connection.writeFrame(responseBody.generateFrame(channelId));

-

-        _connection.closeProtocolSession();

-

-        return true;

-    }

-

-

-    public boolean dispatchConnectionCloseOk(ConnectionCloseOkBody body, int channelId) throws AMQException

-    {

-        _logger.info("Received Connection-close-ok");

-

-        try

-        {

-            _connection.closeSession();

-        }

-        catch (Exception e)

-        {

-            _logger.error("Error closing protocol session: " + e, e);

-        }

-        return true;

-    }

-

-    public boolean dispatchConnectionOpenOk(ConnectionOpenOkBody body, int channelId) throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-    public boolean dispatchConnectionRedirect(ConnectionRedirectBody body, int channelId) throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-    public boolean dispatchConnectionSecure(ConnectionSecureBody body, int channelId) throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-    public boolean dispatchConnectionStart(ConnectionStartBody body, int channelId) throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-    public boolean dispatchConnectionTune(ConnectionTuneBody body, int channelId) throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-

-    public boolean dispatchExchangeBoundOk(ExchangeBoundOkBody body, int channelId) throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-    public boolean dispatchExchangeDeclareOk(ExchangeDeclareOkBody body, int channelId) throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-    public boolean dispatchExchangeDeleteOk(ExchangeDeleteOkBody body, int channelId) throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-    public boolean dispatchQueueBindOk(QueueBindOkBody body, int channelId) throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-    public boolean dispatchQueueDeclareOk(QueueDeclareOkBody body, int channelId) throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-    public boolean dispatchQueueDeleteOk(QueueDeleteOkBody body, int channelId) throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-    public boolean dispatchQueuePurgeOk(QueuePurgeOkBody body, int channelId) throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-    public boolean dispatchTxCommitOk(TxCommitOkBody body, int channelId) throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-    public boolean dispatchTxRollbackOk(TxRollbackOkBody body, int channelId) throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-    public boolean dispatchTxSelectOk(TxSelectOkBody body, int channelId) throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-

-    public boolean dispatchConnectionSecureOk(ConnectionSecureOkBody body, int channelId) throws AMQException

-    {

-        Broker<?> broker = _connection.getBroker();

-

-        SubjectCreator subjectCreator = _connection.getSubjectCreator();

-

-        SaslServer ss = _connection.getSaslServer();

-        if (ss == null)

-        {

-            throw new AMQException("No SASL context set up in session");

-        }

-        MethodRegistry methodRegistry = _connection.getMethodRegistry();

-        SubjectAuthenticationResult authResult = subjectCreator.authenticate(ss, body.getResponse());

-        switch (authResult.getStatus())

-        {

-            case ERROR:

-                Exception cause = authResult.getCause();

-

-                _logger.info("Authentication failed:" + (cause == null ? "" : cause.getMessage()));

-

-                ConnectionCloseBody connectionCloseBody =

-                        methodRegistry.createConnectionCloseBody(AMQConstant.NOT_ALLOWED.getCode(),

-                                                                 AMQConstant.NOT_ALLOWED.getName(),

-                                                                 body.getClazz(),

-                                                                 body.getMethod());

-

-                _connection.writeFrame(connectionCloseBody.generateFrame(0));

-                disposeSaslServer(_connection);

-                break;

-            case SUCCESS:

-                if (_logger.isInfoEnabled())

-                {

-                    _logger.info("Connected as: " + authResult.getSubject());

-                }

-

-                int frameMax = broker.getContextValue(Integer.class, Broker.BROKER_FRAME_SIZE);

-

-                if(frameMax <= 0)

-                {

-                    frameMax = Integer.MAX_VALUE;

-                }

-

-                ConnectionTuneBody tuneBody =

-                        methodRegistry.createConnectionTuneBody(broker.getConnection_sessionCountLimit(),

-                                                                frameMax,

-                                                                broker.getConnection_heartBeatDelay());

-                _connection.writeFrame(tuneBody.generateFrame(0));

-                _connection.setAuthorizedSubject(authResult.getSubject());

-                disposeSaslServer(_connection);

-                break;

-            case CONTINUE:

-

-                ConnectionSecureBody

-                        secureBody = methodRegistry.createConnectionSecureBody(authResult.getChallenge());

-                _connection.writeFrame(secureBody.generateFrame(0));

-        }

-        return true;

-    }

-

-    private void disposeSaslServer(AMQProtocolSession ps)

-    {

-        SaslServer ss = ps.getSaslServer();

-        if (ss != null)

-        {

-            ps.setSaslServer(null);

-            try

-            {

-                ss.dispose();

-            }

-            catch (SaslException e)

-            {

-                _logger.error("Error disposing of Sasl server: " + e);

-            }

-        }

-    }

-

-    public boolean dispatchConnectionStartOk(ConnectionStartOkBody body, int channelId) throws AMQException

-    {

-        Broker<?> broker = _connection.getBroker();

-

-        _logger.info("SASL Mechanism selected: " + body.getMechanism());

-        _logger.info("Locale selected: " + body.getLocale());

-

-        SubjectCreator subjectCreator = _connection.getSubjectCreator();

-        SaslServer ss = null;

-        try

-        {

-            ss = subjectCreator.createSaslServer(String.valueOf(body.getMechanism()),

-                                                 _connection.getLocalFQDN(),

-                                                 _connection.getPeerPrincipal());

-

-            if (ss == null)

-            {

-                throw body.getConnectionException(AMQConstant.RESOURCE_ERROR,

-                                                  "Unable to create SASL Server:" + body.getMechanism(),

-                                                  _connection.getMethodRegistry());

-            }

-

-            _connection.setSaslServer(ss);

-

-            final SubjectAuthenticationResult authResult = subjectCreator.authenticate(ss, body.getResponse());

-            //save clientProperties

-            _connection.setClientProperties(body.getClientProperties());

-

-            MethodRegistry methodRegistry = _connection.getMethodRegistry();

-

-            switch (authResult.getStatus())

-            {

-                case ERROR:

-                    Exception cause = authResult.getCause();

-

-                    _logger.info("Authentication failed:" + (cause == null ? "" : cause.getMessage()));

-

-                    ConnectionCloseBody closeBody =

-                            methodRegistry.createConnectionCloseBody(AMQConstant.NOT_ALLOWED.getCode(),    // replyCode

-                                                                     AMQConstant.NOT_ALLOWED.getName(),

-                                                                     body.getClazz(),

-                                                                     body.getMethod());

-

-                    _connection.writeFrame(closeBody.generateFrame(0));

-                    disposeSaslServer(_connection);

-                    break;

-

-                case SUCCESS:

-                    if (_logger.isInfoEnabled())

-                    {

-                        _logger.info("Connected as: " + authResult.getSubject());

-                    }

-                    _connection.setAuthorizedSubject(authResult.getSubject());

-

-                    int frameMax = broker.getContextValue(Integer.class, Broker.BROKER_FRAME_SIZE);

-

-                    if(frameMax <= 0)

-                    {

-                        frameMax = Integer.MAX_VALUE;

-                    }

-

-                    ConnectionTuneBody

-                            tuneBody = methodRegistry.createConnectionTuneBody(broker.getConnection_sessionCountLimit(),

-                                                                               frameMax,

-                                                                               broker.getConnection_heartBeatDelay());

-                    _connection.writeFrame(tuneBody.generateFrame(0));

-                    break;

-                case CONTINUE:

-                    ConnectionSecureBody

-                            secureBody = methodRegistry.createConnectionSecureBody(authResult.getChallenge());

-                    _connection.writeFrame(secureBody.generateFrame(0));

-            }

-        }

-        catch (SaslException e)

-        {

-            disposeSaslServer(_connection);

-            throw new AMQException("SASL error: " + e, e);

-        }

-        return true;

-    }

-

-    public boolean dispatchConnectionTuneOk(ConnectionTuneOkBody body, int channelId) throws AMQException

-    {

-        final AMQProtocolSession<?> connection = getConnection();

-

-        if (_logger.isDebugEnabled())

-        {

-            _logger.debug(body);

-        }

-

-        connection.initHeartbeats(body.getHeartbeat());

-

-        int brokerFrameMax = connection.getBroker().getContextValue(Integer.class, Broker.BROKER_FRAME_SIZE);

-        if(brokerFrameMax <= 0)

-        {

-            brokerFrameMax = Integer.MAX_VALUE;

-        }

-

-        if(body.getFrameMax() > (long) brokerFrameMax)

-        {

-            throw new AMQConnectionException(AMQConstant.SYNTAX_ERROR,

-                                             "Attempt to set max frame size to " + body.getFrameMax()

-                                             + " greater than the broker will allow: "

-                                             + brokerFrameMax,

-                                             body.getClazz(), body.getMethod(),

-                                             connection.getMethodRegistry(),null);

-        }

-        else if(body.getFrameMax() > 0 && body.getFrameMax() < AMQConstant.FRAME_MIN_SIZE.getCode())

-        {

-            throw new AMQConnectionException(AMQConstant.SYNTAX_ERROR,

-                                             "Attempt to set max frame size to " + body.getFrameMax()

-                                             + " which is smaller than the specification definined minimum: "

-                                             + AMQConstant.FRAME_MIN_SIZE.getCode(),

-                                             body.getClazz(), body.getMethod(),

-                                             connection.getMethodRegistry(),null);

-        }

-        int frameMax = body.getFrameMax() == 0 ? brokerFrameMax : (int) body.getFrameMax();

-        connection.setMaxFrameSize(frameMax);

-

-        long maxChannelNumber = body.getChannelMax();

-        //0 means no implied limit, except that forced by protocol limitations (0xFFFF)

-        connection.setMaximumNumberOfChannels(maxChannelNumber == 0 ? 0xFFFFL : maxChannelNumber);

-        return true;

-    }

-

-    public static final int OK = 0;

-    public static final int EXCHANGE_NOT_FOUND = 1;

-    public static final int QUEUE_NOT_FOUND = 2;

-    public static final int NO_BINDINGS = 3;

-    public static final int QUEUE_NOT_BOUND = 4;

-    public static final int NO_QUEUE_BOUND_WITH_RK = 5;

-    public static final int SPECIFIC_QUEUE_NOT_BOUND_WITH_RK = 6;

-

-    public boolean dispatchExchangeBound(ExchangeBoundBody body, int channelId) throws AMQException

-    {

-        VirtualHostImpl virtualHost = _connection.getVirtualHost();

-        MethodRegistry methodRegistry = _connection.getMethodRegistry();

-

-        final AMQChannel channel = _connection.getChannel(channelId);

-        if (channel == null)

-        {

-            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());

-        }

-        channel.sync();

-

-

-        AMQShortString exchangeName = body.getExchange();

-        AMQShortString queueName = body.getQueue();

-        AMQShortString routingKey = body.getRoutingKey();

-        ExchangeBoundOkBody response;

-

-        if(isDefaultExchange(exchangeName))

-        {

-            if(routingKey == null)

-            {

-                if(queueName == null)

-                {

-                    response = methodRegistry.createExchangeBoundOkBody(virtualHost.getQueues().isEmpty() ? NO_BINDINGS : OK, null);

-                }

-                else

-                {

-                    AMQQueue queue = virtualHost.getQueue(queueName.toString());

-                    if (queue == null)

-                    {

-

-                        response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_FOUND,	// replyCode

-                                                                            AMQShortString.validValueOf("Queue '" + queueName + "' not found"));	// replyText

-                    }

-                    else

-                    {

-                        response = methodRegistry.createExchangeBoundOkBody(OK, null);

-                    }

-                }

-            }

-            else

-            {

-                if(queueName == null)

-                {

-                    response = methodRegistry.createExchangeBoundOkBody(virtualHost.getQueue(routingKey.toString()) == null ? NO_QUEUE_BOUND_WITH_RK : OK, null);

-                }

-                else

-                {

-                    AMQQueue queue = virtualHost.getQueue(queueName.toString());

-                    if (queue == null)

-                    {

-

-                        response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_FOUND,	// replyCode

-                                                                            AMQShortString.validValueOf("Queue '" + queueName + "' not found"));	// replyText

-                    }

-                    else

-                    {

-                        response = methodRegistry.createExchangeBoundOkBody(queueName.equals(routingKey) ? OK : SPECIFIC_QUEUE_NOT_BOUND_WITH_RK, null);

-                    }

-                }

-            }

-        }

-        else

-        {

-            ExchangeImpl exchange = virtualHost.getExchange(exchangeName.toString());

-            if (exchange == null)

-            {

-

-

-                response = methodRegistry.createExchangeBoundOkBody(EXCHANGE_NOT_FOUND,

-                                                                    AMQShortString.validValueOf("Exchange '" + exchangeName + "' not found"));

-            }

-            else if (routingKey == null)

-            {

-                if (queueName == null)

-                {

-                    if (exchange.hasBindings())

-                    {

-                        response = methodRegistry.createExchangeBoundOkBody(OK, null);

-                    }

-                    else

-                    {

-

-                        response = methodRegistry.createExchangeBoundOkBody(NO_BINDINGS,	// replyCode

-                            null);	// replyText

-                    }

-                }

-                else

-                {

-

-                    AMQQueue queue = virtualHost.getQueue(queueName.toString());

-                    if (queue == null)

-                    {

-

-                        response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_FOUND,	// replyCode

-                            AMQShortString.validValueOf("Queue '" + queueName + "' not found"));	// replyText

-                    }

-                    else

-                    {

-                        if (exchange.isBound(queue))

-                        {

-

-                            response = methodRegistry.createExchangeBoundOkBody(OK,	// replyCode

-                                null);	// replyText

-                        }

-                        else

-                        {

-

-                            response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_BOUND,	// replyCode

-                                AMQShortString.validValueOf("Queue '" + queueName + "' not bound to exchange '" + exchangeName + "'"));	// replyText

-                        }

-                    }

-                }

-            }

-            else if (queueName != null)

-            {

-                AMQQueue queue = virtualHost.getQueue(queueName.toString());

-                if (queue == null)

-                {

-

-                    response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_FOUND,	// replyCode

-                        AMQShortString.validValueOf("Queue '" + queueName + "' not found"));	// replyText

-                }

-                else

-                {

-                    String bindingKey = body.getRoutingKey() == null ? null : body.getRoutingKey().asString();

-                    if (exchange.isBound(bindingKey, queue))

-                    {

-

-                        response = methodRegistry.createExchangeBoundOkBody(OK,	// replyCode

-                            null);	// replyText

-                    }

-                    else

-                    {

-

-                        String message = "Queue '" + queueName + "' not bound with routing key '" +

-                                            body.getRoutingKey() + "' to exchange '" + exchangeName + "'";

-

-                        response = methodRegistry.createExchangeBoundOkBody(SPECIFIC_QUEUE_NOT_BOUND_WITH_RK,	// replyCode

-                            AMQShortString.validValueOf(message));	// replyText

-                    }

-                }

-            }

-            else

-            {

-                if (exchange.isBound(body.getRoutingKey() == null ? "" : body.getRoutingKey().asString()))

-                {

-

-                    response = methodRegistry.createExchangeBoundOkBody(OK,	// replyCode

-                        null);	// replyText

-                }

-                else

-                {

-

-                    response = methodRegistry.createExchangeBoundOkBody(NO_QUEUE_BOUND_WITH_RK,	// replyCode

-                        AMQShortString.validValueOf("No queue bound with routing key '" + body.getRoutingKey() +

-                        "' to exchange '" + exchangeName + "'"));	// replyText

-                }

-            }

-        }

-        _connection.writeFrame(response.generateFrame(channelId));

-        return true;

-    }

-

-    public boolean dispatchExchangeDeclare(ExchangeDeclareBody body, int channelId) throws AMQException

-    {

-        VirtualHostImpl virtualHost = _connection.getVirtualHost();

-        final AMQChannel channel = _connection.getChannel(channelId);

-        if (channel == null)

-        {

-            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());

-        }

-

-        final AMQShortString exchangeName = body.getExchange();

-        if (_logger.isDebugEnabled())

-        {

-            _logger.debug("Request to declare exchange of type " + body.getType() + " with name " + exchangeName);

-        }

-

-        ExchangeImpl exchange;

-

-        if(isDefaultExchange(exchangeName))

-        {

-            if(!new AMQShortString(ExchangeDefaults.DIRECT_EXCHANGE_CLASS).equals(body.getType()))

-            {

-                throw new AMQConnectionException(AMQConstant.NOT_ALLOWED, "Attempt to redeclare default exchange: "

-                                                                          + " of type "

-                                                                          + ExchangeDefaults.DIRECT_EXCHANGE_CLASS

-                                                                          + " to " + body.getType() +".",

-                                                 body.getClazz(), body.getMethod(),

-                                                 _connection.getMethodRegistry(),null);

-            }

-        }

-        else

-        {

-            if (body.getPassive())

-            {

-                exchange = virtualHost.getExchange(exchangeName.toString());

-                if(exchange == null)

-                {

-                    throw body.getChannelException(AMQConstant.NOT_FOUND, "Unknown exchange: " + exchangeName,

-                                                   _connection.getMethodRegistry());

-                }

-                else if (!(body.getType() == null || body.getType().length() ==0) && !exchange.getType().equals(body.getType().asString()))

-                {

-

-                    throw new AMQConnectionException(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: " +

-                                      exchangeName + " of type " + exchange.getType()

-                                      + " to " + body.getType() +".",

-                                                     body.getClazz(), body.getMethod(),

-                                                     _connection.getMethodRegistry(),null);

-                }

-

-            }

-            else

-            {

-                try

-                {

-                    String name = exchangeName == null ? null : exchangeName.intern().toString();

-                    String type = body.getType() == null ? null : body.getType().intern().toString();

-

-                    Map<String,Object> attributes = new HashMap<String, Object>();

-                    if(body.getArguments() != null)

-                    {

-                        attributes.putAll(FieldTable.convertToMap(body.getArguments()));

-                    }

-                    attributes.put(org.apache.qpid.server.model.Exchange.ID, null);

-                    attributes.put(org.apache.qpid.server.model.Exchange.NAME,name);

-                    attributes.put(org.apache.qpid.server.model.Exchange.TYPE,type);

-                    attributes.put(org.apache.qpid.server.model.Exchange.DURABLE, body.getDurable());

-                    attributes.put(org.apache.qpid.server.model.Exchange.LIFETIME_POLICY,

-                                   body.getAutoDelete() ? LifetimePolicy.DELETE_ON_NO_LINKS : LifetimePolicy.PERMANENT);

-                    if(!attributes.containsKey(org.apache.qpid.server.model.Exchange.ALTERNATE_EXCHANGE))

-                    {

-                        attributes.put(org.apache.qpid.server.model.Exchange.ALTERNATE_EXCHANGE, null);

-                    }

-                    exchange = virtualHost.createExchange(attributes);

-

-                }

-                catch(ReservedExchangeNameException e)

-                {

-                    throw body.getConnectionException(AMQConstant.NOT_ALLOWED,

-                                                      "Attempt to declare exchange: " + exchangeName +

-                                                      " which begins with reserved prefix.",

-                                                      _connection.getMethodRegistry());

-

-                }

-                catch(ExchangeExistsException e)

-                {

-                    exchange = e.getExistingExchange();

-                    if(!new AMQShortString(exchange.getType()).equals(body.getType()))

-                    {

-                        throw body.getConnectionException(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: "

-                                                                                   + exchangeName + " of type "

-                                                                                   + exchange.getType()

-                                                                                   + " to " + body.getType() + ".",

-                                                          _connection.getMethodRegistry());

-                    }

-                }

-                catch(NoFactoryForTypeException e)

-                {

-                    throw body.getConnectionException(AMQConstant.COMMAND_INVALID,

-                                                      "Unknown exchange type '"

-                                                      + e.getType()

-                                                      + "' for exchange '"

-                                                      + exchangeName

-                                                      + "'",

-                                                      _connection.getMethodRegistry());

-                }

-                catch (AccessControlException e)

-                {

-                    throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,

-                                                      e.getMessage(),

-                                                      _connection.getMethodRegistry());

-                }

-                catch (UnknownConfiguredObjectException e)

-                {

-                    // note - since 0-8/9/9-1 can't set the alt. exchange this exception should never occur

-                    throw body.getConnectionException(AMQConstant.NOT_FOUND,

-                                                      "Unknown alternate exchange "

-                                                      + (e.getName() != null

-                                                              ? "name: \"" + e.getName() + "\""

-                                                              : "id: " + e.getId()),

-                                                      _connection.getMethodRegistry());

-                }

-                catch (IllegalArgumentException e)

-                {

-                    throw body.getConnectionException(AMQConstant.COMMAND_INVALID,

-                                                      "Error creating exchange '"

-                                                      + exchangeName

-                                                      + "': "

-                                                      + e.getMessage(),

-                                                      _connection.getMethodRegistry());

-                }

-            }

-        }

-

-        if(!body.getNowait())

-        {

-            MethodRegistry methodRegistry = _connection.getMethodRegistry();

-            AMQMethodBody responseBody = methodRegistry.createExchangeDeclareOkBody();

-            channel.sync();

-            _connection.writeFrame(responseBody.generateFrame(channelId));

-        }

-        return true;

-    }

-

-    public boolean dispatchExchangeDelete(ExchangeDeleteBody body, int channelId) throws AMQException

-    {

-        VirtualHostImpl virtualHost = _connection.getVirtualHost();

-        final AMQChannel channel = _connection.getChannel(channelId);

-        if (channel == null)

-        {

-            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());

-        }

-        channel.sync();

-        try

-        {

-

-            if(isDefaultExchange(body.getExchange()))

-            {

-                throw body.getConnectionException(AMQConstant.NOT_ALLOWED,

-                                                  "Default Exchange cannot be deleted",

-                                                  _connection.getMethodRegistry());

-            }

-

-            final String exchangeName = body.getExchange().toString();

-

-            final ExchangeImpl exchange = virtualHost.getExchange(exchangeName);

-            if(exchange == null)

-            {

-                throw body.getChannelException(AMQConstant.NOT_FOUND, "No such exchange: " + body.getExchange(),

-                                               _connection.getMethodRegistry());

-            }

-

-            virtualHost.removeExchange(exchange, !body.getIfUnused());

-

-            ExchangeDeleteOkBody responseBody = _connection.getMethodRegistry().createExchangeDeleteOkBody();

-

-            _connection.writeFrame(responseBody.generateFrame(channelId));

-        }

-

-        catch (ExchangeIsAlternateException e)

-        {

-            throw body.getChannelException(AMQConstant.NOT_ALLOWED, "Exchange in use as an alternate exchange",

-                                           _connection.getMethodRegistry());

-

-        }

-        catch (RequiredExchangeException e)

-        {

-            throw body.getChannelException(AMQConstant.NOT_ALLOWED,

-                                           "Exchange '" + body.getExchange() + "' cannot be deleted",

-                                           _connection.getMethodRegistry());

-        }

-        catch (AccessControlException e)

-        {

-            throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,

-                                              e.getMessage(),

-                                              _connection.getMethodRegistry());

-        }

-        return true;

-    }

-

-    private boolean isDefaultExchange(final AMQShortString exchangeName)

-    {

-        return exchangeName == null || exchangeName.equals(AMQShortString.EMPTY_STRING);

-    }

-

-    public boolean dispatchQueueBind(QueueBindBody body, int channelId) throws AMQException

-    {

-        VirtualHostImpl virtualHost = _connection.getVirtualHost();

-        AMQChannel channel = _connection.getChannel(channelId);

-

-        if (channel == null)

-        {

-            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());

-        }

-

-        final AMQQueue queue;

-        final AMQShortString routingKey;

-

-        final AMQShortString queueName = body.getQueue();

-

-        if (queueName == null)

-        {

-

-            queue = channel.getDefaultQueue();

-

-            if (queue == null)

-            {

-                throw body.getChannelException(AMQConstant.NOT_FOUND,

-                                               "No default queue defined on channel and queue was null",

-                                               _connection.getMethodRegistry());

-            }

-

-            if (body.getRoutingKey() == null)

-            {

-                routingKey = AMQShortString.valueOf(queue.getName());

-            }

-            else

-            {

-                routingKey = body.getRoutingKey().intern();

-            }

-        }

-        else

-        {

-            queue = virtualHost.getQueue(queueName.toString());

-            routingKey = body.getRoutingKey() == null ? AMQShortString.EMPTY_STRING : body.getRoutingKey().intern();

-        }

-

-        if (queue == null)

-        {

-            throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + queueName + " does not exist.",

-                                           _connection.getMethodRegistry());

-        }

-

-        if(isDefaultExchange(body.getExchange()))

-        {

-            throw body.getConnectionException(AMQConstant.NOT_ALLOWED,

-                                              "Cannot bind the queue " + queueName + " to the default exchange",

-                                              _connection.getMethodRegistry());

-        }

-

-        final String exchangeName = body.getExchange().toString();

-

-        final ExchangeImpl exch = virtualHost.getExchange(exchangeName);

-        if (exch == null)

-        {

-            throw body.getChannelException(AMQConstant.NOT_FOUND, "Exchange " + exchangeName + " does not exist.",

-                                           _connection.getMethodRegistry());

-        }

-

-

-        try

-        {

-

-            Map<String,Object> arguments = FieldTable.convertToMap(body.getArguments());

-            String bindingKey = String.valueOf(routingKey);

-

-            if (!exch.isBound(bindingKey, arguments, queue))

-            {

-

-                if(!exch.addBinding(bindingKey, queue, arguments) && ExchangeDefaults.TOPIC_EXCHANGE_CLASS.equals(exch.getType()))

-                {

-                    exch.replaceBinding(bindingKey, queue, arguments);

-                }

-            }

-        }

-        catch (AccessControlException e)

-        {

-            throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,

-                                              e.getMessage(),

-                                              _connection.getMethodRegistry());

-        }

-

-        if (_logger.isInfoEnabled())

-        {

-            _logger.info("Binding queue " + queue + " to exchange " + exch + " with routing key " + routingKey);

-        }

-        if (!body.getNowait())

-        {

-            channel.sync();

-            MethodRegistry methodRegistry = _connection.getMethodRegistry();

-            AMQMethodBody responseBody = methodRegistry.createQueueBindOkBody();

-            _connection.writeFrame(responseBody.generateFrame(channelId));

-

-        }

-        return true;

-    }

-

-    public boolean dispatchQueueDeclare(QueueDeclareBody body, int channelId) throws AMQException

-    {

-        final AMQSessionModel session = _connection.getChannel(channelId);

-        VirtualHostImpl virtualHost = _connection.getVirtualHost();

-

-        final AMQShortString queueName;

-

-        // if we aren't given a queue name, we create one which we return to the client

-        if ((body.getQueue() == null) || (body.getQueue().length() == 0))

-        {

-            queueName = new AMQShortString("tmp_" + UUID.randomUUID());

-        }

-        else

-        {

-            queueName = body.getQueue().intern();

-        }

-

-        AMQQueue queue;

-

-        //TODO: do we need to check that the queue already exists with exactly the same "configuration"?

-

-        AMQChannel channel = _connection.getChannel(channelId);

-

-        if (channel == null)

-        {

-            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());

-        }

-

-        if(body.getPassive())

-        {

-            queue = virtualHost.getQueue(queueName.toString());

-            if (queue == null)

-            {

-                String msg = "Queue: " + queueName + " not found on VirtualHost(" + virtualHost + ").";

-                throw body.getChannelException(AMQConstant.NOT_FOUND, msg, _connection.getMethodRegistry());

-            }

-            else

-            {

-                if (!queue.verifySessionAccess(channel))

-                {

-                    throw body.getConnectionException(AMQConstant.NOT_ALLOWED,

-                                                      "Queue "

-                                                      + queue.getName()

-                                                      + " is exclusive, but not created on this Connection.",

-                                                      _connection.getMethodRegistry());

-                }

-

-                //set this as the default queue on the channel:

-                channel.setDefaultQueue(queue);

-            }

-        }

-        else

-        {

-

-            try

-            {

-

-                queue = createQueue(channel, queueName, body, virtualHost, _connection);

-

-            }

-            catch(QueueExistsException qe)

-            {

-

-                queue = qe.getExistingQueue();

-

-                if (!queue.verifySessionAccess(channel))

-                {

-                    throw body.getConnectionException(AMQConstant.NOT_ALLOWED,

-                                                      "Queue "

-                                                      + queue.getName()

-                                                      + " is exclusive, but not created on this Connection.",

-                                                      _connection.getMethodRegistry());

-                }

-                else if(queue.isExclusive() != body.getExclusive())

-                {

-

-                    throw body.getChannelException(AMQConstant.ALREADY_EXISTS,

-                                                   "Cannot re-declare queue '"

-                                                   + queue.getName()

-                                                   + "' with different exclusivity (was: "

-                                                   + queue.isExclusive()

-                                                   + " requested "

-                                                   + body.getExclusive()

-                                                   + ")",

-                                                   _connection.getMethodRegistry());

-                }

-                else if((body.getAutoDelete() && queue.getLifetimePolicy() != LifetimePolicy.DELETE_ON_NO_OUTBOUND_LINKS)

-                    || (!body.getAutoDelete() && queue.getLifetimePolicy() != ((body.getExclusive() && !body.getDurable()) ? LifetimePolicy.DELETE_ON_CONNECTION_CLOSE : LifetimePolicy.PERMANENT)))

-                {

-                    throw body.getChannelException(AMQConstant.ALREADY_EXISTS,

-                                                   "Cannot re-declare queue '"

-                                                   + queue.getName()

-                                                   + "' with different lifetime policy (was: "

-                                                   + queue.getLifetimePolicy()

-                                                   + " requested autodelete: "

-                                                   + body.getAutoDelete()

-                                                   + ")",

-                                                   _connection.getMethodRegistry());

-                }

-                else if(queue.isDurable() != body.getDurable())

-                {

-                    throw body.getChannelException(AMQConstant.ALREADY_EXISTS,

-                                                   "Cannot re-declare queue '"

-                                                   + queue.getName()

-                                                   + "' with different durability (was: "

-                                                   + queue.isDurable()

-                                                   + " requested "

-                                                   + body.getDurable()

-                                                   + ")",

-                                                   _connection.getMethodRegistry());

-                }

-

-            }

-            catch (AccessControlException e)

-            {

-                throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,

-                                                  e.getMessage(),

-                                                  _connection.getMethodRegistry());

-            }

-

-            //set this as the default queue on the channel:

-            channel.setDefaultQueue(queue);

-        }

-

-        if (!body.getNowait())

-        {

-            channel.sync();

-            MethodRegistry methodRegistry = _connection.getMethodRegistry();

-            QueueDeclareOkBody responseBody =

-                    methodRegistry.createQueueDeclareOkBody(queueName,

-                                                            queue.getQueueDepthMessages(),

-                                                            queue.getConsumerCount());

-            _connection.writeFrame(responseBody.generateFrame(channelId));

-

-            _logger.info("Queue " + queueName + " declared successfully");

-        }

-        return true;

-    }

-

-    protected AMQQueue createQueue(final AMQChannel channel, final AMQShortString queueName,

-                                   QueueDeclareBody body,

-                                   final VirtualHostImpl virtualHost,

-                                   final AMQProtocolSession session)

-            throws AMQException, QueueExistsException

-    {

-

-        final boolean durable = body.getDurable();

-        final boolean autoDelete = body.getAutoDelete();

-        final boolean exclusive = body.getExclusive();

-

-

-        Map<String, Object> attributes =

-                QueueArgumentsConverter.convertWireArgsToModel(FieldTable.convertToMap(body.getArguments()));

-        final String queueNameString = AMQShortString.toString(queueName);

-        attributes.put(Queue.NAME, queueNameString);

-        attributes.put(Queue.ID, UUID.randomUUID());

-        attributes.put(Queue.DURABLE, durable);

-

-        LifetimePolicy lifetimePolicy;

-        ExclusivityPolicy exclusivityPolicy;

-

-        if(exclusive)

-        {

-            lifetimePolicy = autoDelete

-                    ? LifetimePolicy.DELETE_ON_NO_OUTBOUND_LINKS

-                    : durable ? LifetimePolicy.PERMANENT : LifetimePolicy.DELETE_ON_CONNECTION_CLOSE;

-            exclusivityPolicy = durable ? ExclusivityPolicy.CONTAINER : ExclusivityPolicy.CONNECTION;

-        }

-        else

-        {

-            lifetimePolicy = autoDelete ? LifetimePolicy.DELETE_ON_NO_OUTBOUND_LINKS : LifetimePolicy.PERMANENT;

-            exclusivityPolicy = ExclusivityPolicy.NONE;

-        }

-

-        attributes.put(Queue.EXCLUSIVE, exclusivityPolicy);

-        attributes.put(Queue.LIFETIME_POLICY, lifetimePolicy);

-

-

-        final AMQQueue queue = virtualHost.createQueue(attributes);

-

-        return queue;

-    }

-

-    public boolean dispatchQueueDelete(QueueDeleteBody body, int channelId) throws AMQException

-    {

-        VirtualHostImpl virtualHost = _connection.getVirtualHost();

-

-        AMQChannel channel = _connection.getChannel(channelId);

-

-        if (channel == null)

-        {

-            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());

-        }

-        channel.sync();

-        AMQQueue queue;

-        if (body.getQueue() == null)

-        {

-

-            //get the default queue on the channel:

-            queue = channel.getDefaultQueue();

-        }

-        else

-        {

-            queue = virtualHost.getQueue(body.getQueue().toString());

-        }

-

-        if (queue == null)

-        {

-            throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + body.getQueue() + " does not exist.",

-                                           _connection.getMethodRegistry());

-

-        }

-        else

-        {

-            if (body.getIfEmpty() && !queue.isEmpty())

-            {

-                throw body.getChannelException(AMQConstant.IN_USE, "Queue: " + body.getQueue() + " is not empty.",

-                                               _connection.getMethodRegistry());

-            }

-            else if (body.getIfUnused() && !queue.isUnused())

-            {

-                // TODO - Error code

-                throw body.getChannelException(AMQConstant.IN_USE, "Queue: " + body.getQueue() + " is still used.",

-                                               _connection.getMethodRegistry());

-            }

-            else

-            {

-                if (!queue.verifySessionAccess(channel))

-                {

-                    throw body.getConnectionException(AMQConstant.NOT_ALLOWED,

-                                                      "Queue "

-                                                      + queue.getName()

-                                                      + " is exclusive, but not created on this Connection.",

-                                                      _connection.getMethodRegistry());

-                }

-

-                int purged = 0;

-                try

-                {

-                    purged = virtualHost.removeQueue(queue);

-                }

-                catch (AccessControlException e)

-                {

-                    throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,

-                                                      e.getMessage(),

-                                                      _connection.getMethodRegistry());

-                }

-

-                MethodRegistry methodRegistry = _connection.getMethodRegistry();

-                QueueDeleteOkBody responseBody = methodRegistry.createQueueDeleteOkBody(purged);

-                _connection.writeFrame(responseBody.generateFrame(channelId));

-            }

-        }

-        return true;

-    }

-

-    public boolean dispatchQueuePurge(QueuePurgeBody body, int channelId) throws AMQException

-    {

-        VirtualHostImpl virtualHost = _connection.getVirtualHost();

-

-        AMQChannel channel = _connection.getChannel(channelId);

-        if (channel == null)

-        {

-            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());

-        }

-        AMQQueue queue;

-        if(body.getQueue() == null)

-        {

-

-           //get the default queue on the channel:

-           queue = channel.getDefaultQueue();

-

-            if(queue == null)

-            {

-                throw body.getConnectionException(AMQConstant.NOT_ALLOWED,

-                                                  "No queue specified.",

-                                                  _connection.getMethodRegistry());

-            }

-        }

-        else

-        {

-            queue = virtualHost.getQueue(body.getQueue().toString());

-        }

-

-        if(queue == null)

-        {

-            throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + body.getQueue() + " does not exist.",

-                                           _connection.getMethodRegistry());

-        }

-        else

-        {

-                if (!queue.verifySessionAccess(channel))

-                {

-                    throw body.getConnectionException(AMQConstant.NOT_ALLOWED,

-                                                      "Queue is exclusive, but not created on this Connection.",

-                                                      _connection.getMethodRegistry());

-                }

-

-            long purged = 0;

-            try

-            {

-                purged = queue.clearQueue();

-            }

-            catch (AccessControlException e)

-            {

-                throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,

-                                                  e.getMessage(),

-                                                  _connection.getMethodRegistry());

-            }

-

-

-            if(!body.getNowait())

-                {

-                    channel.sync();

-                    MethodRegistry methodRegistry = _connection.getMethodRegistry();

-                    AMQMethodBody responseBody = methodRegistry.createQueuePurgeOkBody(purged);

-                    _connection.writeFrame(responseBody.generateFrame(channelId));

-

-                }

-        }

-        return true;

-    }

-

-

-    public boolean dispatchTxCommit(TxCommitBody body, final int channelId) throws AMQException

-    {

-        try

-        {

-            if (_logger.isDebugEnabled())

-            {

-                _logger.debug("Commit received on channel " + channelId);

-            }

-            AMQChannel channel = _connection.getChannel(channelId);

-

-            if (channel == null)

-            {

-                throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());

-            }

-            channel.commit(new Runnable()

-            {

-

-                @Override

-                public void run()

-                {

-                    MethodRegistry methodRegistry = _connection.getMethodRegistry();

-                    AMQMethodBody responseBody = methodRegistry.createTxCommitOkBody();

-                    _connection.writeFrame(responseBody.generateFrame(channelId));

-                }

-            }, true);

-

-

-

-        }

-        catch (AMQException e)

-        {

-            throw body.getChannelException(e.getErrorCode(), "Failed to commit: " + e.getMessage(),

-                                           _connection.getMethodRegistry());

-        }

-        return true;

-    }

-

-    public boolean dispatchTxRollback(TxRollbackBody body, final int channelId) throws AMQException

-    {

-        try

-        {

-            AMQChannel channel = _connection.getChannel(channelId);

-

-            if (channel == null)

-            {

-                throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());

-            }

-

-

-

-            final MethodRegistry methodRegistry = _connection.getMethodRegistry();

-            final AMQMethodBody responseBody = methodRegistry.createTxRollbackOkBody();

-

-            Runnable task = new Runnable()

-            {

-

-                public void run()

-                {

-                    _connection.writeFrame(responseBody.generateFrame(channelId));

-                }

-            };

-

-            channel.rollback(task);

-

-            //Now resend all the unacknowledged messages back to the original subscribers.

-            //(Must be done after the TxnRollback-ok response).

-            // Why, are we not allowed to send messages back to client before the ok method?

-            channel.resend();

-

-        }

-        catch (AMQException e)

-        {

-            throw body.getChannelException(e.getErrorCode(), "Failed to rollback: " + e.getMessage(),

-                                           _connection.getMethodRegistry());

-        }

-        return true;

-    }

-

-    public boolean dispatchTxSelect(TxSelectBody body, int channelId) throws AMQException

-    {

-        AMQChannel channel = _connection.getChannel(channelId);

-

-        if (channel == null)

-        {

-            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());

-        }

-

-        channel.setLocalTransactional();

-

-        MethodRegistry methodRegistry = _connection.getMethodRegistry();

-        TxSelectOkBody responseBody = methodRegistry.createTxSelectOkBody();

-        _connection.writeFrame(responseBody.generateFrame(channelId));

-        return true;

-    }

-

-    public boolean dispatchBasicRecoverSync(BasicRecoverSyncBody body, int channelId) throws AMQException

-    {

-        final AMQProtocolSession<?> connection = getConnection();

-

-        _logger.debug("Recover received on protocol session " + connection + " and channel " + channelId);

-        AMQChannel channel = connection.getChannel(channelId);

-

-

-        if (channel == null)

-        {

-            throw body.getChannelNotFoundException(channelId, connection.getMethodRegistry());

-        }

-        channel.sync();

-        channel.resend();

-

-        MethodRegistry methodRegistry = connection.getMethodRegistry();

-        AMQMethodBody recoverOk = methodRegistry.createBasicRecoverSyncOkBody();

-        connection.writeFrame(recoverOk.generateFrame(channelId));

-

-        return true;

-    }

-

-    public boolean dispatchBasicRecoverSyncOk(BasicRecoverSyncOkBody body, int channelId) throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-    @Override

-    public boolean dispatchChannelAlert(final ChannelAlertBody body, final int channelId)

-            throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-    public boolean dispatchQueueUnbindOk(QueueUnbindOkBody body, int channelId) throws AMQException

-    {

-        throw new UnexpectedMethodException(body);

-    }

-

-    public boolean dispatchQueueUnbind(QueueUnbindBody body, int channelId) throws AMQException

-    {

-        final AMQProtocolSession<?> connection = getConnection();

-

-        if (ProtocolVersion.v8_0.equals(connection.getProtocolVersion()))

-        {

-            // 0-8 does not support QueueUnbind

-            throw new AMQException(AMQConstant.COMMAND_INVALID, "QueueUnbind not present in AMQP version: " + connection.getProtocolVersion(), null);

-        }

-

-        VirtualHostImpl virtualHost = connection.getVirtualHost();

-

-        final AMQQueue queue;

-        final AMQShortString routingKey;

-

-

-        AMQChannel channel = connection.getChannel(channelId);

-        if (channel == null)

-        {

-            throw body.getChannelNotFoundException(channelId, connection.getMethodRegistry());

-        }

-

-        if (body.getQueue() == null)

-        {

-

-            queue = channel.getDefaultQueue();

-

-            if (queue == null)

-            {

-                throw body.getChannelException(AMQConstant.NOT_FOUND,

-                                               "No default queue defined on channel and queue was null",

-                                               connection.getMethodRegistry());

-            }

-

-            routingKey = body.getRoutingKey() == null ? null : body.getRoutingKey().intern(false);

-

-        }

-        else

-        {

-            queue = virtualHost.getQueue(body.getQueue().toString());

-            routingKey = body.getRoutingKey() == null ? null : body.getRoutingKey().intern(false);

-        }

-

-        if (queue == null)

-        {

-            throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + body.getQueue() + " does not exist.",

-                                           connection.getMethodRegistry());

-        }

-

-        if(isDefaultExchange(body.getExchange()))

-        {

-            throw body.getConnectionException(AMQConstant.NOT_ALLOWED,

-                                              "Cannot unbind the queue "

-                                              + queue.getName()

-                                              + " from the default exchange", connection.getMethodRegistry());

-        }

-

-        final ExchangeImpl exch = virtualHost.getExchange(body.getExchange() == null ? null : body.getExchange().toString());

-        if (exch == null)

-        {

-            throw body.getChannelException(AMQConstant.NOT_FOUND, "Exchange " + body.getExchange() + " does not exist.",

-                                           connection.getMethodRegistry());

-        }

-

-        if(!exch.hasBinding(String.valueOf(routingKey), queue))

-        {

-            throw body.getChannelException(AMQConstant.NOT_FOUND, "No such binding", connection.getMethodRegistry());

-        }

-        else

-        {

-            try

-            {

-                exch.deleteBinding(String.valueOf(routingKey), queue);

-            }

-            catch (AccessControlException e)

-            {

-                throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,

-                                                  e.getMessage(),

-                                                  connection.getMethodRegistry());

-            }

-        }

-

-

-        if (_logger.isInfoEnabled())

-        {

-            _logger.info("Binding queue " + queue + " to exchange " + exch + " with routing key " + routingKey);

-        }

-

-

-        final AMQMethodBody responseBody = connection.getMethodRegistry().createQueueUnbindOkBody();

-        channel.sync();

-        connection.writeFrame(responseBody.generateFrame(channelId));

-        return true;

-    }

-

-}

+/*
+ *
+ * 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.server.protocol.v0_8;
+
+import java.security.AccessControlException;
+import java.security.PrivilegedAction;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.security.auth.Subject;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.AMQConnectionException;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.exchange.ExchangeDefaults;
+import org.apache.qpid.framing.*;
+import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.server.consumer.ConsumerImpl;
+import org.apache.qpid.server.exchange.ExchangeImpl;
+import org.apache.qpid.server.filter.AMQInvalidArgumentException;
+import org.apache.qpid.server.flow.FlowCreditManager;
+import org.apache.qpid.server.flow.MessageOnlyCreditManager;
+import org.apache.qpid.server.message.InstanceProperties;
+import org.apache.qpid.server.message.MessageDestination;
+import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.MessageSource;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.ExclusivityPolicy;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.NoFactoryForTypeException;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.UnknownConfiguredObjectException;
+import org.apache.qpid.server.model.port.AmqpPort;
+import org.apache.qpid.server.protocol.AMQSessionModel;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.queue.QueueArgumentsConverter;
+import org.apache.qpid.server.security.SubjectCreator;
+import org.apache.qpid.server.security.auth.SubjectAuthenticationResult;
+import org.apache.qpid.server.virtualhost.ExchangeExistsException;
+import org.apache.qpid.server.virtualhost.ExchangeIsAlternateException;
+import org.apache.qpid.server.virtualhost.QueueExistsException;
+import org.apache.qpid.server.virtualhost.RequiredExchangeException;
+import org.apache.qpid.server.virtualhost.ReservedExchangeNameException;
+import org.apache.qpid.server.virtualhost.VirtualHostImpl;
+
+public class ServerMethodDispatcherImpl implements MethodDispatcher
+{
+    private static final Logger _logger = Logger.getLogger(ServerMethodDispatcherImpl.class);
+
+    private final AMQProtocolSession<?> _connection;
+
+
+    private static interface ChannelAction
+    {
+        void onChannel(ChannelMethodProcessor channel);
+    }
+
+    public static MethodDispatcher createMethodDispatcher(AMQProtocolSession<?> connection)
+    {
+        return new ServerMethodDispatcherImpl(connection);
+    }
+
+
+    public ServerMethodDispatcherImpl(AMQProtocolSession<?> connection)
+    {
+        _connection = connection;
+    }
+
+
+    protected final AMQProtocolSession<?> getConnection()
+    {
+        return _connection;
+    }
+
+    private void processChannelMethod(int channelId, final ChannelAction action)
+    {
+        final AMQChannel channel = _connection.getChannel(channelId);
+        if (channel == null)
+        {
+            // TODO throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+        }
+        else
+        {
+            Subject.doAs(channel.getSubject(), new PrivilegedAction<Void>()
+            {
+                @Override
+                public Void run()
+                {
+                    action.onChannel(channel.getMethodProcessor());
+                    return null;
+                }
+            });
+        }
+
+    }
+
+    public boolean dispatchAccessRequest(AccessRequestBody body, int channelId) throws AMQException
+    {
+        final AMQChannel channel = _connection.getChannel(channelId);
+        if (channel == null)
+        {
+            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+        }
+
+        MethodRegistry methodRegistry = _connection.getMethodRegistry();
+
+        if(ProtocolVersion.v0_91.equals(_connection.getProtocolVersion()) )
+        {
+            throw new AMQException(AMQConstant.COMMAND_INVALID, "AccessRequest not present in AMQP versions other than 0-8, 0-9");
+        }
+
+        // We don't implement access control class, but to keep clients happy that expect it
+        // always use the "0" ticket.
+        AccessRequestOkBody response = methodRegistry.createAccessRequestOkBody(0);
+        channel.sync();
+        _connection.writeFrame(response.generateFrame(channelId));
+        return true;
+    }
+
+    public boolean dispatchBasicAck(BasicAckBody body, int channelId) throws AMQException
+    {
+
+        if (_logger.isDebugEnabled())
+        {
+            _logger.debug("Ack(Tag:" + body.getDeliveryTag() + ":Mult:" + body.getMultiple() + ") received on channel " + channelId);
+        }
+
+        final AMQChannel channel = _connection.getChannel(channelId);
+
+        if (channel == null)
+        {
+            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+        }
+
+        // this method throws an AMQException if the delivery tag is not known
+        channel.acknowledgeMessage(body.getDeliveryTag(), body.getMultiple());
+        return true;
+    }
+
+    public boolean dispatchBasicCancel(BasicCancelBody body, int channelId) throws AMQException
+    {
+        final AMQChannel channel = _connection.getChannel(channelId);
+
+
+        if (channel == null)
+        {
+            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+        }
+
+        if (_logger.isDebugEnabled())
+        {
+            _logger.debug("BasicCancel: for:" + body.getConsumerTag() +
+                       " nowait:" + body.getNowait());
+        }
+
+        channel.unsubscribeConsumer(body.getConsumerTag());
+        if (!body.getNowait())
+        {
+            MethodRegistry methodRegistry = _connection.getMethodRegistry();
+            BasicCancelOkBody cancelOkBody = methodRegistry.createBasicCancelOkBody(body.getConsumerTag());
+            channel.sync();
+            _connection.writeFrame(cancelOkBody.generateFrame(channelId));
+        }
+        return true;
+    }
+
+    public boolean dispatchBasicConsume(BasicConsumeBody body, int channelId) throws AMQException
+    {
+        AMQChannel channel = _connection.getChannel(channelId);
+        VirtualHostImpl<?,?,?> vHost = _connection.getVirtualHost();
+
+        if (channel == null)
+        {
+            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+        }
+        else
+        {
+            channel.sync();
+            String queueName = body.getQueue() == null ? null : body.getQueue().asString();
+            if (_logger.isDebugEnabled())
+            {
+                _logger.debug("BasicConsume: from '" + queueName +
+                              "' for:" + body.getConsumerTag() +
+                              " nowait:" + body.getNowait() +
+                              " args:" + body.getArguments());
+            }
+
+            MessageSource queue = queueName == null ? channel.getDefaultQueue() : vHost.getQueue(queueName);
+            final Collection<MessageSource> sources = new HashSet<>();
+            if(queue != null)
+            {
+                sources.add(queue);
+            }
+            else if(vHost.getContextValue(Boolean.class, "qpid.enableMultiQueueConsumers")
+                    && body.getArguments() != null
+                    && body.getArguments().get("x-multiqueue") instanceof Collection)
+            {
+                for(Object object : (Collection<Object>) body.getArguments().get("x-multiqueue"))
+                {
+                    String sourceName = String.valueOf(object);
+                    sourceName = sourceName.trim();
+                    if(sourceName.length() != 0)
+                    {
+                        MessageSource source = vHost.getMessageSource(sourceName);
+                        if(source == null)
+                        {
+                            sources.clear();
+                            break;
+                        }
+                        else
+                        {
+                            sources.add(source);
+                        }
+                    }
+                }
+                queueName = body.getArguments().get("x-multiqueue").toString();
+            }
+
+            if (sources.isEmpty())
+            {
+                if (_logger.isDebugEnabled())
+                {
+                    _logger.debug("No queue for '" + queueName + "'");
+                }
+                if (queueName != null)
+                {
+                    String msg = "No such queue, '" + queueName + "'";
+                    throw body.getChannelException(AMQConstant.NOT_FOUND, msg, _connection.getMethodRegistry());
+                }
+                else
+                {
+                    String msg = "No queue name provided, no default queue defined.";
+                    throw body.getConnectionException(AMQConstant.NOT_ALLOWED, msg, _connection.getMethodRegistry());
+                }
+            }
+            else
+            {
+                final AMQShortString consumerTagName;
+
+                if (body.getConsumerTag() != null)
+                {
+                    consumerTagName = body.getConsumerTag().intern(false);
+                }
+                else
+                {
+                    consumerTagName = null;
+                }
+
+                try
+                {
+                    if(consumerTagName == null || channel.getSubscription(consumerTagName) == null)
+                    {
+
+                        AMQShortString consumerTag = channel.consumeFromSource(consumerTagName,
+                                                                               sources,
+                                                                               !body.getNoAck(),
+                                                                               body.getArguments(),
+                                                                               body.getExclusive(),
+                                                                               body.getNoLocal());
+                        if (!body.getNowait())
+                        {
+                            MethodRegistry methodRegistry = _connection.getMethodRegistry();
+                            AMQMethodBody responseBody = methodRegistry.createBasicConsumeOkBody(consumerTag);
+                            _connection.writeFrame(responseBody.generateFrame(channelId));
+
+                        }
+                    }
+                    else
+                    {
+                        AMQShortString msg = AMQShortString.validValueOf("Non-unique consumer tag, '" + body.getConsumerTag() + "'");
+
+                        MethodRegistry methodRegistry = _connection.getMethodRegistry();
+                        AMQMethodBody responseBody = methodRegistry.createConnectionCloseBody(AMQConstant.NOT_ALLOWED.getCode(),    // replyCode
+                                                                 msg,               // replytext
+                                                                 body.getClazz(),
+                                                                 body.getMethod());
+                        _connection.writeFrame(responseBody.generateFrame(0));
+                    }
+
+                }
+                catch (AMQInvalidArgumentException ise)
+                {
+                    _logger.debug("Closing connection due to invalid selector");
+
+                    MethodRegistry methodRegistry = _connection.getMethodRegistry();
+                    AMQMethodBody responseBody = methodRegistry.createChannelCloseBody(AMQConstant.ARGUMENT_INVALID.getCode(),
+                                                                                       AMQShortString.validValueOf(ise.getMessage()),
+                                                                                       body.getClazz(),
+                                                                                       body.getMethod());
+                    _connection.writeFrame(responseBody.generateFrame(channelId));
+
+
+                }
+                catch (AMQQueue.ExistingExclusiveConsumer e)
+                {
+                    throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+                                                      "Cannot subscribe to queue "
+                                                      + queue.getName()
+                                                      + " as it already has an existing exclusive consumer",
+                                                      _connection.getMethodRegistry());
+                }
+                catch (AMQQueue.ExistingConsumerPreventsExclusive e)
+                {
+                    throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+                                                      "Cannot subscribe to queue "
+                                                      + queue.getName()
+                                                      + " exclusively as it already has a consumer",
+                                                      _connection.getMethodRegistry());
+                }
+                catch (AccessControlException e)
+                {
+                    throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+                                                      "Cannot subscribe to queue "
+                                                      + queue.getName()
+                                                      + " permission denied", _connection.getMethodRegistry());
+                }
+                catch (MessageSource.ConsumerAccessRefused consumerAccessRefused)
+                {
+                    throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+                                                      "Cannot subscribe to queue "
+                                                      + queue.getName()
+                                                      + " as it already has an incompatible exclusivity policy",
+                                                      _connection.getMethodRegistry());
+                }
+
+            }
+        }
+        return true;
+    }
+
+    public boolean dispatchBasicGet(BasicGetBody body, int channelId) throws AMQException
+    {
+
+        VirtualHostImpl vHost = _connection.getVirtualHost();
+
+        AMQChannel channel = _connection.getChannel(channelId);
+        if (channel == null)
+        {
+            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+        }
+        else
+        {
+            channel.sync();
+            AMQQueue queue = body.getQueue() == null ? channel.getDefaultQueue() : vHost.getQueue(body.getQueue().toString());
+            if (queue == null)
+            {
+                _logger.info("No queue for '" + body.getQueue() + "'");
+                if(body.getQueue()!=null)
+                {
+                    throw body.getConnectionException(AMQConstant.NOT_FOUND,
+                                                      "No such queue, '" + body.getQueue() + "'",
+                                                      _connection.getMethodRegistry());
+                }
+                else
+                {
+                    throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+                                                      "No queue name provided, no default queue defined.",
+                                                      _connection.getMethodRegistry());
+                }
+            }
+            else
+            {
+
+                try
+                {
+                    if (!performGet(queue, _connection, channel, !body.getNoAck()))
+                    {
+                        MethodRegistry methodRegistry = _connection.getMethodRegistry();
+
+                        BasicGetEmptyBody responseBody = methodRegistry.createBasicGetEmptyBody(null);
+
+
+                        _connection.writeFrame(responseBody.generateFrame(channelId));
+                    }
+                }
+                catch (AccessControlException e)
+                {
+                    throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+                                                      e.getMessage(), _connection.getMethodRegistry());
+                }
+                catch (MessageSource.ExistingExclusiveConsumer e)
+                {
+                    throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+                                                      "Queue has an exclusive consumer",
+                                                      _connection.getMethodRegistry());
+                }
+                catch (MessageSource.ExistingConsumerPreventsExclusive e)
+                {
+                    throw body.getConnectionException(AMQConstant.INTERNAL_ERROR,
+                                                      "The GET request has been evaluated as an exclusive consumer, " +
+                                                      "this is likely due to a programming error in the Qpid broker",
+                                                      _connection.getMethodRegistry());
+                }
+                catch (MessageSource.ConsumerAccessRefused consumerAccessRefused)
+                {
+                    throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+                                                      "Queue has an incompatible exclusivit policy",
+                                                      _connection.getMethodRegistry());
+                }
+            }
+        }
+        return true;
+    }
+
+    public static boolean performGet(final AMQQueue queue,
+                                     final AMQProtocolSession session,
+                                     final AMQChannel channel,
+                                     final boolean acks)
+            throws AMQException, MessageSource.ExistingConsumerPreventsExclusive,
+                   MessageSource.ExistingExclusiveConsumer, MessageSource.ConsumerAccessRefused
+    {
+
+        final FlowCreditManager singleMessageCredit = new MessageOnlyCreditManager(1L);
+
+        final GetDeliveryMethod getDeliveryMethod =
+                new GetDeliveryMethod(singleMessageCredit, session, channel, queue);
+        final RecordDeliveryMethod getRecordMethod = new RecordDeliveryMethod()
+        {
+
+            public void recordMessageDelivery(final ConsumerImpl sub, final MessageInstance entry, final long deliveryTag)
+            {
+                channel.addUnacknowledgedMessage(entry, deliveryTag, null);
+            }
+        };
+
+        ConsumerTarget_0_8 target;
+        EnumSet<ConsumerImpl.Option> options = EnumSet.of(ConsumerImpl.Option.TRANSIENT, ConsumerImpl.Option.ACQUIRES,
+                                                          ConsumerImpl.Option.SEES_REQUEUES);
+        if(acks)
+        {
+
+            target = ConsumerTarget_0_8.createAckTarget(channel,
+                                                        AMQShortString.EMPTY_STRING, null,
+                                                        singleMessageCredit, getDeliveryMethod, getRecordMethod);
+        }
+        else
+        {
+            target = ConsumerTarget_0_8.createGetNoAckTarget(channel,
+                                                             AMQShortString.EMPTY_STRING, null,
+                                                             singleMessageCredit, getDeliveryMethod, getRecordMethod);
+        }
+
+        ConsumerImpl sub = queue.addConsumer(target, null, AMQMessage.class, "", options);
+        sub.flush();
+        sub.close();
+        return(getDeliveryMethod.hasDeliveredMessage());
+
+
+    }
+
+
+    private static class GetDeliveryMethod implements ClientDeliveryMethod
+    {
+
+        private final FlowCreditManager _singleMessageCredit;
+        private final AMQProtocolSession _session;
+        private final AMQChannel _channel;
+        private final AMQQueue _queue;
+        private boolean _deliveredMessage;
+
+        public GetDeliveryMethod(final FlowCreditManager singleMessageCredit,
+                                 final AMQProtocolSession session,
+                                 final AMQChannel channel, final AMQQueue queue)
+        {
+            _singleMessageCredit = singleMessageCredit;
+            _session = session;
+            _channel = channel;
+            _queue = queue;
+        }
+
+        @Override
+        public long deliverToClient(final ConsumerImpl sub, final ServerMessage message,
+                                    final InstanceProperties props, final long deliveryTag)
+        {
+            _singleMessageCredit.useCreditForMessage(message.getSize());
+            long size =_session.getProtocolOutputConverter().writeGetOk(message,
+                                                                        props,
+                                                                        _channel.getChannelId(),
+                                                                        deliveryTag,
+                                                                        _queue.getQueueDepthMessages());
+
+            _deliveredMessage = true;
+            return size;
+        }
+
+        public boolean hasDeliveredMessage()
+        {
+            return _deliveredMessage;
+        }
+    }
+
+    public boolean dispatchBasicPublish(BasicPublishBody body, int channelId) throws AMQException
+    {
+        if (_logger.isDebugEnabled())
+        {
+            _logger.debug("Publish received on channel " + channelId);
+        }
+
+        AMQShortString exchangeName = body.getExchange();
+        VirtualHostImpl vHost = _connection.getVirtualHost();
+
+        // TODO: check the delivery tag field details - is it unique across the broker or per subscriber?
+
+        MessageDestination destination;
+
+        if (exchangeName == null || AMQShortString.EMPTY_STRING.equals(exchangeName))
+        {
+            destination = vHost.getDefaultDestination();
+        }
+        else
+        {
+            destination = vHost.getMessageDestination(exchangeName.toString());
+        }
+
+        // if the exchange does not exist we raise a channel exception
+        if (destination == null)
+        {
+            throw body.getChannelException(AMQConstant.NOT_FOUND, "Unknown exchange name",
+                                           _connection.getMethodRegistry());
+        }
+        else
+        {
+            // The partially populated BasicDeliver frame plus the received route body
+            // is stored in the channel. Once the final body frame has been received
+            // it is routed to the exchange.
+            AMQChannel channel = _connection.getChannel(channelId);
+
+            if (channel == null)
+            {
+                throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+            }
+
+            MessagePublishInfo info = new MessagePublishInfo(body.getExchange(),
+                                                             body.getImmediate(),
+                                                             body.getMandatory(),
+                                                             body.getRoutingKey());
+            info.setExchange(exchangeName);
+            try
+            {
+                channel.setPublishFrame(info, destination);
+            }
+            catch (AccessControlException e)
+            {
+                throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+                                                  e.getMessage(),
+                                                  _connection.getMethodRegistry());
+            }
+        }
+        return true;
+    }
+
+    public boolean dispatchBasicQos(BasicQosBody body, int channelId) throws AMQException
+    {
+        AMQChannel channel = _connection.getChannel(channelId);
+        if (channel == null)
+        {
+            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+        }
+        channel.sync();
+        channel.setCredit(body.getPrefetchSize(), body.getPrefetchCount());
+
+
+        MethodRegistry methodRegistry = _connection.getMethodRegistry();
+        AMQMethodBody responseBody = methodRegistry.createBasicQosOkBody();
+        _connection.writeFrame(responseBody.generateFrame(channelId));
+
+        return true;
+    }
+
+    public boolean dispatchBasicRecover(BasicRecoverBody body, int channelId) throws AMQException
+    {
+        _logger.debug("Recover received on protocol session " + _connection
+                                                + " and channel " + channelId);
+        AMQChannel channel = _connection.getChannel(channelId);
+
+
+        if (channel == null)
+        {
+            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+        }
+
+        channel.resend();
+
+        // Qpid 0-8 hacks a synchronous -ok onto recover.
+        // In Qpid 0-9 we create a separate sync-recover, sync-recover-ok pair to be "more" compliant
+        if(_connection.getProtocolVersion().equals(ProtocolVersion.v8_0))
+        {
+            MethodRegistry methodRegistry = _connection.getMethodRegistry();
+            AMQMethodBody recoverOk = methodRegistry.createBasicRecoverSyncOkBody();
+            channel.sync();
+            _connection.writeFrame(recoverOk.generateFrame(channelId));
+
+        }
+
+        return true;
+    }
+
+    public boolean dispatchBasicReject(BasicRejectBody body, int channelId) throws AMQException
+    {
+
+        AMQChannel channel = _connection.getChannel(channelId);
+
+        if (channel == null)
+        {
+            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+        }
+
+        if (_logger.isDebugEnabled())
+        {
+            _logger.debug("Rejecting:" + body.getDeliveryTag() +
+                          ": Requeue:" + body.getRequeue() +
+                          " on channel:" + channel.debugIdentity());
+        }
+
+        long deliveryTag = body.getDeliveryTag();
+
+        MessageInstance message = channel.getUnacknowledgedMessageMap().get(deliveryTag);
+
+        if (message == null)
+        {
+            _logger.warn("Dropping reject request as message is null for tag:" + deliveryTag);
+        }
+        else
+        {
+
+            if (message.getMessage() == null)
+            {
+                _logger.warn("Message has already been purged, unable to Reject.");
+            }
+            else
+            {
+
+                if (_logger.isDebugEnabled())
+                {
+                    _logger.debug("Rejecting: DT:" + deliveryTag + "-" + message.getMessage() +
+                                  ": Requeue:" + body.getRequeue() +
+                                  " on channel:" + channel.debugIdentity());
+                }
+
+                if (body.getRequeue())
+                {
+                    //this requeue represents a message rejected from the pre-dispatch queue
+                    //therefore we need to amend the delivery counter.
+                    message.decrementDeliveryCount();
+
+                    channel.requeue(deliveryTag);
+                }
+                else
+                {
+                    // Since the Java client abuses the reject flag for requeing after rollback, we won't set reject here
+                    // as it would prevent redelivery
+                    // message.reject();
+
+                    final boolean maxDeliveryCountEnabled = channel.isMaxDeliveryCountEnabled(deliveryTag);
+                    _logger.debug("maxDeliveryCountEnabled: "
+                                  + maxDeliveryCountEnabled
+                                  + " deliveryTag "
+                                  + deliveryTag);
+                    if (maxDeliveryCountEnabled)
+                    {
+                        final boolean deliveredTooManyTimes = channel.isDeliveredTooManyTimes(deliveryTag);
+                        _logger.debug("deliveredTooManyTimes: "
+                                      + deliveredTooManyTimes
+                                      + " deliveryTag "
+                                      + deliveryTag);
+                        if (deliveredTooManyTimes)
+                        {
+                            channel.deadLetter(body.getDeliveryTag());
+                        }
+                        else
+                        {
+                            //this requeue represents a message rejected because of a recover/rollback that we
+                            //are not ready to DLQ. We rely on the reject command to resend from the unacked map
+                            //and therefore need to increment the delivery counter so we cancel out the effect
+                            //of the AMQChannel#resend() decrement.
+                            message.incrementDeliveryCount();
+                        }
+                    }
+                    else
+                    {
+                        channel.requeue(deliveryTag);
+                    }
+                }
+            }
+        }
+        return true;
+    }
+
+    public boolean dispatchChannelOpen(ChannelOpenBody body, int channelId) throws AMQException
+    {
+        VirtualHostImpl virtualHost = _connection.getVirtualHost();
+
+        // Protect the broker against out of order frame request.
+        if (virtualHost == null)
+        {
+            throw new AMQException(AMQConstant.COMMAND_INVALID, "Virtualhost has not yet been set. ConnectionOpen has not been called.", null);
+        }
+        _logger.info("Connecting to: " + virtualHost.getName());
+
+        final AMQChannel channel = new AMQChannel(_connection, channelId, virtualHost.getMessageStore());
+
+        _connection.addChannel(channel);
+
+        ChannelOpenOkBody response;
+
+
+        response = _connection.getMethodRegistry().createChannelOpenOkBody();
+
+
+        _connection.writeFrame(response.generateFrame(channelId));
+        return true;
+    }
+
+
+    public boolean dispatchAccessRequestOk(AccessRequestOkBody body, int channelId) throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+
+    public boolean dispatchBasicCancelOk(BasicCancelOkBody body, int channelId) throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+    public boolean dispatchBasicConsumeOk(BasicConsumeOkBody body, int channelId) throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+    public boolean dispatchBasicDeliver(BasicDeliverBody body, int channelId) throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+    public boolean dispatchBasicGetEmpty(BasicGetEmptyBody body, int channelId) throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+    public boolean dispatchBasicGetOk(BasicGetOkBody body, int channelId) throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+    public boolean dispatchBasicQosOk(BasicQosOkBody body, int channelId) throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+    public boolean dispatchBasicReturn(BasicReturnBody body, int channelId) throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+    public boolean dispatchChannelClose(ChannelCloseBody body, int channelId) throws AMQException
+    {
+
+        if (_logger.isInfoEnabled())
+        {
+            _logger.info("Received channel close for id " + channelId
+                                             + " citing class " + body.getClassId() +
+                         " and method " + body.getMethodId());
+        }
+
+
+        AMQChannel channel = _connection.getChannel(channelId);
+
+        if (channel == null)
+        {
+            throw body.getConnectionException(AMQConstant.CHANNEL_ERROR,
+                                              "Trying to close unknown channel",
+                                              _connection.getMethodRegistry());
+        }
+        channel.sync();
+        _connection.closeChannel(channelId);
+        // Client requested closure so we don't wait for ok we send it
+        _connection.closeChannelOk(channelId);
+
+        MethodRegistry methodRegistry = _connection.getMethodRegistry();
+        ChannelCloseOkBody responseBody = methodRegistry.createChannelCloseOkBody();
+        _connection.writeFrame(responseBody.generateFrame(channelId));
+        return true;
+    }
+
+
+    public boolean dispatchChannelCloseOk(ChannelCloseOkBody body, int channelId) throws AMQException
+    {
+
+        _logger.info("Received channel-close-ok for channel-id " + channelId);
+
+        // Let the Protocol Session know the channel is now closed.
+        _connection.closeChannelOk(channelId);
+        return true;
+    }
+
+
+    public boolean dispatchChannelFlow(ChannelFlowBody body, int channelId) throws AMQException
+    {
+        final AMQProtocolSession<?> connection = getConnection();
+
+
+        AMQChannel channel = connection.getChannel(channelId);
+
+        if (channel == null)
+        {
+            throw body.getChannelNotFoundException(channelId, connection.getMethodRegistry());
+        }
+        channel.sync();
+        channel.setSuspended(!body.getActive());
+        _logger.debug("Channel.Flow for channel " + channelId + ", active=" + body.getActive());
+
+        MethodRegistry methodRegistry = connection.getMethodRegistry();
+        AMQMethodBody responseBody = methodRegistry.createChannelFlowOkBody(body.getActive());
+        connection.writeFrame(responseBody.generateFrame(channelId));
+        return true;
+    }
+
+    public boolean dispatchChannelFlowOk(ChannelFlowOkBody body, int channelId) throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+    public boolean dispatchChannelOpenOk(ChannelOpenOkBody body, int channelId) throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+
+    public boolean dispatchConnectionOpen(ConnectionOpenBody body, int channelId) throws AMQException
+    {
+
+        //ignore leading '/'
+        String virtualHostName;
+        if ((body.getVirtualHost() != null) && body.getVirtualHost().charAt(0) == '/')
+        {
+            virtualHostName = new StringBuilder(body.getVirtualHost().subSequence(1, body.getVirtualHost().length())).toString();
+        }
+        else
+        {
+            virtualHostName = body.getVirtualHost() == null ? null : String.valueOf(body.getVirtualHost());
+        }
+
+        VirtualHostImpl virtualHost = ((AmqpPort) _connection.getPort()).getVirtualHost(virtualHostName);
+
+        if (virtualHost == null)
+        {
+            throw body.getConnectionException(AMQConstant.NOT_FOUND, "Unknown virtual host: '" + virtualHostName + "'",
+                                              _connection.getMethodRegistry());
+        }
+        else
+        {
+            // Check virtualhost access
+            if (virtualHost.getState() != State.ACTIVE)
+            {
+                throw body.getConnectionException(AMQConstant.CONNECTION_FORCED,
+                                                  "Virtual host '" + virtualHost.getName() + "' is not active",
+                                                  _connection.getMethodRegistry());
+            }
+
+            _connection.setVirtualHost(virtualHost);
+            try
+            {
+                virtualHost.getSecurityManager().authoriseCreateConnection(_connection);
+            }
+            catch (AccessControlException e)
+            {
+                throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+                                                  e.getMessage(),
+                                                  _connection.getMethodRegistry());
+            }
+
+            // See Spec (0.8.2). Section  3.1.2 Virtual Hosts
+            if (_connection.getContextKey() == null)
+            {
+                _connection.setContextKey(new AMQShortString(Long.toString(System.currentTimeMillis())));
+            }
+
+            MethodRegistry methodRegistry = _connection.getMethodRegistry();
+            AMQMethodBody responseBody =  methodRegistry.createConnectionOpenOkBody(body.getVirtualHost());
+
+            _connection.writeFrame(responseBody.generateFrame(channelId));
+        }
+        return true;
+    }
+
+
+    public boolean dispatchConnectionClose(ConnectionCloseBody body, int channelId) throws AMQException
+    {
+        if (_logger.isInfoEnabled())
+        {
+            _logger.info("ConnectionClose received with reply code/reply text " + body.getReplyCode() + "/" +
+                         body.getReplyText() + " for " + _connection);
+        }
+        try
+        {
+            _connection.closeSession();
+        }
+        catch (Exception e)
+        {
+            _logger.error("Error closing protocol session: " + e, e);
+        }
+
+        MethodRegistry methodRegistry = _connection.getMethodRegistry();
+        ConnectionCloseOkBody responseBody = methodRegistry.createConnectionCloseOkBody();
+        _connection.writeFrame(responseBody.generateFrame(channelId));
+
+        _connection.closeProtocolSession();
+
+        return true;
+    }
+
+
+    public boolean dispatchConnectionCloseOk(ConnectionCloseOkBody body, int channelId) throws AMQException
+    {
+        _logger.info("Received Connection-close-ok");
+
+        try
+        {
+            _connection.closeSession();
+        }
+        catch (Exception e)
+        {
+            _logger.error("Error closing protocol session: " + e, e);
+        }
+        return true;
+    }
+
+    public boolean dispatchConnectionOpenOk(ConnectionOpenOkBody body, int channelId) throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+    public boolean dispatchConnectionRedirect(ConnectionRedirectBody body, int channelId) throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+    public boolean dispatchConnectionSecure(ConnectionSecureBody body, int channelId) throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+    public boolean dispatchConnectionStart(ConnectionStartBody body, int channelId) throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+    public boolean dispatchConnectionTune(ConnectionTuneBody body, int channelId) throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+
+    public boolean dispatchExchangeBoundOk(ExchangeBoundOkBody body, int channelId) throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+    public boolean dispatchExchangeDeclareOk(ExchangeDeclareOkBody body, int channelId) throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+    public boolean dispatchExchangeDeleteOk(ExchangeDeleteOkBody body, int channelId) throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+    public boolean dispatchQueueBindOk(QueueBindOkBody body, int channelId) throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+    public boolean dispatchQueueDeclareOk(QueueDeclareOkBody body, int channelId) throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+    public boolean dispatchQueueDeleteOk(QueueDeleteOkBody body, int channelId) throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+    public boolean dispatchQueuePurgeOk(QueuePurgeOkBody body, int channelId) throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+    public boolean dispatchTxCommitOk(TxCommitOkBody body, int channelId) throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+    public boolean dispatchTxRollbackOk(TxRollbackOkBody body, int channelId) throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+    public boolean dispatchTxSelectOk(TxSelectOkBody body, int channelId) throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+
+    public boolean dispatchConnectionSecureOk(ConnectionSecureOkBody body, int channelId) throws AMQException
+    {
+        Broker<?> broker = _connection.getBroker();
+
+        SubjectCreator subjectCreator = _connection.getSubjectCreator();
+
+        SaslServer ss = _connection.getSaslServer();
+        if (ss == null)
+        {
+            throw new AMQException("No SASL context set up in session");
+        }
+        MethodRegistry methodRegistry = _connection.getMethodRegistry();
+        SubjectAuthenticationResult authResult = subjectCreator.authenticate(ss, body.getResponse());
+        switch (authResult.getStatus())
+        {
+            case ERROR:
+                Exception cause = authResult.getCause();
+
+                _logger.info("Authentication failed:" + (cause == null ? "" : cause.getMessage()));
+
+                ConnectionCloseBody connectionCloseBody =
+                        methodRegistry.createConnectionCloseBody(AMQConstant.NOT_ALLOWED.getCode(),
+                                                                 AMQConstant.NOT_ALLOWED.getName(),
+                                                                 body.getClazz(),
+                                                                 body.getMethod());
+
+                _connection.writeFrame(connectionCloseBody.generateFrame(0));
+                disposeSaslServer(_connection);
+                break;
+            case SUCCESS:
+                if (_logger.isInfoEnabled())
+                {
+                    _logger.info("Connected as: " + authResult.getSubject());
+                }
+
+                int frameMax = broker.getContextValue(Integer.class, Broker.BROKER_FRAME_SIZE);
+
+                if(frameMax <= 0)
+                {
+                    frameMax = Integer.MAX_VALUE;
+                }
+
+                ConnectionTuneBody tuneBody =
+                        methodRegistry.createConnectionTuneBody(broker.getConnection_sessionCountLimit(),
+                                                                frameMax,
+                                                                broker.getConnection_heartBeatDelay());
+                _connection.writeFrame(tuneBody.generateFrame(0));
+                _connection.setAuthorizedSubject(authResult.getSubject());
+                disposeSaslServer(_connection);
+                break;
+            case CONTINUE:
+
+                ConnectionSecureBody
+                        secureBody = methodRegistry.createConnectionSecureBody(authResult.getChallenge());
+                _connection.writeFrame(secureBody.generateFrame(0));
+        }
+        return true;
+    }
+
+    private void disposeSaslServer(AMQProtocolSession ps)
+    {
+        SaslServer ss = ps.getSaslServer();
+        if (ss != null)
+        {
+            ps.setSaslServer(null);
+            try
+            {
+                ss.dispose();
+            }
+            catch (SaslException e)
+            {
+                _logger.error("Error disposing of Sasl server: " + e);
+            }
+        }
+    }
+
+    public boolean dispatchConnectionStartOk(ConnectionStartOkBody body, int channelId) throws AMQException
+    {
+        Broker<?> broker = _connection.getBroker();
+
+        _logger.info("SASL Mechanism selected: " + body.getMechanism());
+        _logger.info("Locale selected: " + body.getLocale());
+
+        SubjectCreator subjectCreator = _connection.getSubjectCreator();
+        SaslServer ss = null;
+        try
+        {
+            ss = subjectCreator.createSaslServer(String.valueOf(body.getMechanism()),
+                                                 _connection.getLocalFQDN(),
+                                                 _connection.getPeerPrincipal());
+
+            if (ss == null)
+            {
+                throw body.getConnectionException(AMQConstant.RESOURCE_ERROR,
+                                                  "Unable to create SASL Server:" + body.getMechanism(),
+                                                  _connection.getMethodRegistry());
+            }
+
+            _connection.setSaslServer(ss);
+
+            final SubjectAuthenticationResult authResult = subjectCreator.authenticate(ss, body.getResponse());
+            //save clientProperties
+            _connection.setClientProperties(body.getClientProperties());
+
+            MethodRegistry methodRegistry = _connection.getMethodRegistry();
+
+            switch (authResult.getStatus())
+            {
+                case ERROR:
+                    Exception cause = authResult.getCause();
+
+                    _logger.info("Authentication failed:" + (cause == null ? "" : cause.getMessage()));
+
+                    ConnectionCloseBody closeBody =
+                            methodRegistry.createConnectionCloseBody(AMQConstant.NOT_ALLOWED.getCode(),    // replyCode
+                                                                     AMQConstant.NOT_ALLOWED.getName(),
+                                                                     body.getClazz(),
+                                                                     body.getMethod());
+
+                    _connection.writeFrame(closeBody.generateFrame(0));
+                    disposeSaslServer(_connection);
+                    break;
+
+                case SUCCESS:
+                    if (_logger.isInfoEnabled())
+                    {
+                        _logger.info("Connected as: " + authResult.getSubject());
+                    }
+                    _connection.setAuthorizedSubject(authResult.getSubject());
+
+                    int frameMax = broker.getContextValue(Integer.class, Broker.BROKER_FRAME_SIZE);
+
+                    if(frameMax <= 0)
+                    {
+                        frameMax = Integer.MAX_VALUE;
+                    }
+
+                    ConnectionTuneBody
+                            tuneBody = methodRegistry.createConnectionTuneBody(broker.getConnection_sessionCountLimit(),
+                                                                               frameMax,
+                                                                               broker.getConnection_heartBeatDelay());
+                    _connection.writeFrame(tuneBody.generateFrame(0));
+                    break;
+                case CONTINUE:
+                    ConnectionSecureBody
+                            secureBody = methodRegistry.createConnectionSecureBody(authResult.getChallenge());
+                    _connection.writeFrame(secureBody.generateFrame(0));
+            }
+        }
+        catch (SaslException e)
+        {
+            disposeSaslServer(_connection);
+            throw new AMQException("SASL error: " + e, e);
+        }
+        return true;
+    }
+
+    public boolean dispatchConnectionTuneOk(ConnectionTuneOkBody body, int channelId) throws AMQException
+    {
+        final AMQProtocolSession<?> connection = getConnection();
+
+        if (_logger.isDebugEnabled())
+        {
+            _logger.debug(body);
+        }
+
+        connection.initHeartbeats(body.getHeartbeat());
+
+        int brokerFrameMax = connection.getBroker().getContextValue(Integer.class, Broker.BROKER_FRAME_SIZE);
+        if(brokerFrameMax <= 0)
+        {
+            brokerFrameMax = Integer.MAX_VALUE;
+        }
+
+        if(body.getFrameMax() > (long) brokerFrameMax)
+        {
+            throw new AMQConnectionException(AMQConstant.SYNTAX_ERROR,
+                                             "Attempt to set max frame size to " + body.getFrameMax()
+                                             + " greater than the broker will allow: "
+                                             + brokerFrameMax,
+                                             body.getClazz(), body.getMethod(),
+                                             connection.getMethodRegistry(),null);
+        }
+        else if(body.getFrameMax() > 0 && body.getFrameMax() < AMQConstant.FRAME_MIN_SIZE.getCode())
+        {
+            throw new AMQConnectionException(AMQConstant.SYNTAX_ERROR,
+                                             "Attempt to set max frame size to " + body.getFrameMax()
+                                             + " which is smaller than the specification definined minimum: "
+                                             + AMQConstant.FRAME_MIN_SIZE.getCode(),
+                                             body.getClazz(), body.getMethod(),
+                                             connection.getMethodRegistry(),null);
+        }
+        int frameMax = body.getFrameMax() == 0 ? brokerFrameMax : (int) body.getFrameMax();
+        connection.setMaxFrameSize(frameMax);
+
+        long maxChannelNumber = body.getChannelMax();
+        //0 means no implied limit, except that forced by protocol limitations (0xFFFF)
+        connection.setMaximumNumberOfChannels(maxChannelNumber == 0 ? 0xFFFFL : maxChannelNumber);
+        return true;
+    }
+
+    public static final int OK = 0;
+    public static final int EXCHANGE_NOT_FOUND = 1;
+    public static final int QUEUE_NOT_FOUND = 2;
+    public static final int NO_BINDINGS = 3;
+    public static final int QUEUE_NOT_BOUND = 4;
+    public static final int NO_QUEUE_BOUND_WITH_RK = 5;
+    public static final int SPECIFIC_QUEUE_NOT_BOUND_WITH_RK = 6;
+
+    public boolean dispatchExchangeBound(ExchangeBoundBody body, int channelId) throws AMQException
+    {
+        VirtualHostImpl virtualHost = _connection.getVirtualHost();
+        MethodRegistry methodRegistry = _connection.getMethodRegistry();
+
+        final AMQChannel channel = _connection.getChannel(channelId);
+        if (channel == null)
+        {
+            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+        }
+        channel.sync();
+
+
+        AMQShortString exchangeName = body.getExchange();
+        AMQShortString queueName = body.getQueue();
+        AMQShortString routingKey = body.getRoutingKey();
+        ExchangeBoundOkBody response;
+
+        if(isDefaultExchange(exchangeName))
+        {
+            if(routingKey == null)
+            {
+                if(queueName == null)
+                {
+                    response = methodRegistry.createExchangeBoundOkBody(virtualHost.getQueues().isEmpty() ? NO_BINDINGS : OK, null);
+                }
+                else
+                {
+                    AMQQueue queue = virtualHost.getQueue(queueName.toString());
+                    if (queue == null)
+                    {
+
+                        response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_FOUND,	// replyCode
+                                                                            AMQShortString.validValueOf("Queue '" + queueName + "' not found"));	// replyText
+                    }
+                    else
+                    {
+                        response = methodRegistry.createExchangeBoundOkBody(OK, null);
+                    }
+                }
+            }
+            else
+            {
+                if(queueName == null)
+                {
+                    response = methodRegistry.createExchangeBoundOkBody(virtualHost.getQueue(routingKey.toString()) == null ? NO_QUEUE_BOUND_WITH_RK : OK, null);
+                }
+                else
+                {
+                    AMQQueue queue = virtualHost.getQueue(queueName.toString());
+                    if (queue == null)
+                    {
+
+                        response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_FOUND,	// replyCode
+                                                                            AMQShortString.validValueOf("Queue '" + queueName + "' not found"));	// replyText
+                    }
+                    else
+                    {
+                        response = methodRegistry.createExchangeBoundOkBody(queueName.equals(routingKey) ? OK : SPECIFIC_QUEUE_NOT_BOUND_WITH_RK, null);
+                    }
+                }
+            }
+        }
+        else
+        {
+            ExchangeImpl exchange = virtualHost.getExchange(exchangeName.toString());
+            if (exchange == null)
+            {
+
+
+                response = methodRegistry.createExchangeBoundOkBody(EXCHANGE_NOT_FOUND,
+                                                                    AMQShortString.validValueOf("Exchange '" + exchangeName + "' not found"));
+            }
+            else if (routingKey == null)
+            {
+                if (queueName == null)
+                {
+                    if (exchange.hasBindings())
+                    {
+                        response = methodRegistry.createExchangeBoundOkBody(OK, null);
+                    }
+                    else
+                    {
+
+                        response = methodRegistry.createExchangeBoundOkBody(NO_BINDINGS,	// replyCode
+                            null);	// replyText
+                    }
+                }
+                else
+                {
+
+                    AMQQueue queue = virtualHost.getQueue(queueName.toString());
+                    if (queue == null)
+                    {
+
+                        response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_FOUND,	// replyCode
+                            AMQShortString.validValueOf("Queue '" + queueName + "' not found"));	// replyText
+                    }
+                    else
+                    {
+                        if (exchange.isBound(queue))
+                        {
+
+                            response = methodRegistry.createExchangeBoundOkBody(OK,	// replyCode
+                                null);	// replyText
+                        }
+                        else
+                        {
+
+                            response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_BOUND,	// replyCode
+                                AMQShortString.validValueOf("Queue '" + queueName + "' not bound to exchange '" + exchangeName + "'"));	// replyText
+                        }
+                    }
+                }
+            }
+            else if (queueName != null)
+            {
+                AMQQueue queue = virtualHost.getQueue(queueName.toString());
+                if (queue == null)
+                {
+
+                    response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_FOUND,	// replyCode
+                        AMQShortString.validValueOf("Queue '" + queueName + "' not found"));	// replyText
+                }
+                else
+                {
+                    String bindingKey = body.getRoutingKey() == null ? null : body.getRoutingKey().asString();
+                    if (exchange.isBound(bindingKey, queue))
+                    {
+
+                        response = methodRegistry.createExchangeBoundOkBody(OK,	// replyCode
+                            null);	// replyText
+                    }
+                    else
+                    {
+
+                        String message = "Queue '" + queueName + "' not bound with routing key '" +
+                                            body.getRoutingKey() + "' to exchange '" + exchangeName + "'";
+
+                        response = methodRegistry.createExchangeBoundOkBody(SPECIFIC_QUEUE_NOT_BOUND_WITH_RK,	// replyCode
+                            AMQShortString.validValueOf(message));	// replyText
+                    }
+                }
+            }
+            else
+            {
+                if (exchange.isBound(body.getRoutingKey() == null ? "" : body.getRoutingKey().asString()))
+                {
+
+                    response = methodRegistry.createExchangeBoundOkBody(OK,	// replyCode
+                        null);	// replyText
+                }
+                else
+                {
+
+                    response = methodRegistry.createExchangeBoundOkBody(NO_QUEUE_BOUND_WITH_RK,	// replyCode
+                        AMQShortString.validValueOf("No queue bound with routing key '" + body.getRoutingKey() +
+                        "' to exchange '" + exchangeName + "'"));	// replyText
+                }
+            }
+        }
+        _connection.writeFrame(response.generateFrame(channelId));
+        return true;
+    }
+
+    public boolean dispatchExchangeDeclare(ExchangeDeclareBody body, int channelId) throws AMQException
+    {
+        VirtualHostImpl virtualHost = _connection.getVirtualHost();
+        final AMQChannel channel = _connection.getChannel(channelId);
+        if (channel == null)
+        {
+            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+        }
+
+        final AMQShortString exchangeName = body.getExchange();
+        if (_logger.isDebugEnabled())
+        {
+            _logger.debug("Request to declare exchange of type " + body.getType() + " with name " + exchangeName);
+        }
+
+        ExchangeImpl exchange;
+
+        if(isDefaultExchange(exchangeName))
+        {
+            if(!new AMQShortString(ExchangeDefaults.DIRECT_EXCHANGE_CLASS).equals(body.getType()))
+            {
+                throw new AMQConnectionException(AMQConstant.NOT_ALLOWED, "Attempt to redeclare default exchange: "
+                                                                          + " of type "
+                                                                          + ExchangeDefaults.DIRECT_EXCHANGE_CLASS
+                                                                          + " to " + body.getType() +".",
+                                                 body.getClazz(), body.getMethod(),
+                                                 _connection.getMethodRegistry(),null);
+            }
+        }
+        else
+        {
+            if (body.getPassive())
+            {
+                exchange = virtualHost.getExchange(exchangeName.toString());
+                if(exchange == null)
+                {
+                    throw body.getChannelException(AMQConstant.NOT_FOUND, "Unknown exchange: " + exchangeName,
+                                                   _connection.getMethodRegistry());
+                }
+                else if (!(body.getType() == null || body.getType().length() ==0) && !exchange.getType().equals(body.getType().asString()))
+                {
+
+                    throw new AMQConnectionException(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: " +
+                                      exchangeName + " of type " + exchange.getType()
+                                      + " to " + body.getType() +".",
+                                                     body.getClazz(), body.getMethod(),
+                                                     _connection.getMethodRegistry(),null);
+                }
+
+            }
+            else
+            {
+                try
+                {
+                    String name = exchangeName == null ? null : exchangeName.intern().toString();
+                    String type = body.getType() == null ? null : body.getType().intern().toString();
+
+                    Map<String,Object> attributes = new HashMap<String, Object>();
+                    if(body.getArguments() != null)
+                    {
+                        attributes.putAll(FieldTable.convertToMap(body.getArguments()));
+                    }
+                    attributes.put(org.apache.qpid.server.model.Exchange.ID, null);
+                    attributes.put(org.apache.qpid.server.model.Exchange.NAME,name);
+                    attributes.put(org.apache.qpid.server.model.Exchange.TYPE,type);
+                    attributes.put(org.apache.qpid.server.model.Exchange.DURABLE, body.getDurable());
+                    attributes.put(org.apache.qpid.server.model.Exchange.LIFETIME_POLICY,
+                                   body.getAutoDelete() ? LifetimePolicy.DELETE_ON_NO_LINKS : LifetimePolicy.PERMANENT);
+                    if(!attributes.containsKey(org.apache.qpid.server.model.Exchange.ALTERNATE_EXCHANGE))
+                    {
+                        attributes.put(org.apache.qpid.server.model.Exchange.ALTERNATE_EXCHANGE, null);
+                    }
+                    exchange = virtualHost.createExchange(attributes);
+
+                }
+                catch(ReservedExchangeNameException e)
+                {
+                    throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+                                                      "Attempt to declare exchange: " + exchangeName +
+                                                      " which begins with reserved prefix.",
+                                                      _connection.getMethodRegistry());
+
+                }
+                catch(ExchangeExistsException e)
+                {
+                    exchange = e.getExistingExchange();
+                    if(!new AMQShortString(exchange.getType()).equals(body.getType()))
+                    {
+                        throw body.getConnectionException(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: "
+                                                                                   + exchangeName + " of type "
+                                                                                   + exchange.getType()
+                                                                                   + " to " + body.getType() + ".",
+                                                          _connection.getMethodRegistry());
+                    }
+                }
+                catch(NoFactoryForTypeException e)
+                {
+                    throw body.getConnectionException(AMQConstant.COMMAND_INVALID,
+                                                      "Unknown exchange type '"
+                                                      + e.getType()
+                                                      + "' for exchange '"
+                                                      + exchangeName
+                                                      + "'",
+                                                      _connection.getMethodRegistry());
+                }
+                catch (AccessControlException e)
+                {
+                    throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+                                                      e.getMessage(),
+                                                      _connection.getMethodRegistry());
+                }
+                catch (UnknownConfiguredObjectException e)
+                {
+                    // note - since 0-8/9/9-1 can't set the alt. exchange this exception should never occur
+                    throw body.getConnectionException(AMQConstant.NOT_FOUND,
+                                                      "Unknown alternate exchange "
+                                                      + (e.getName() != null
+                                                              ? "name: \"" + e.getName() + "\""
+                                                              : "id: " + e.getId()),
+                                                      _connection.getMethodRegistry());
+                }
+                catch (IllegalArgumentException e)
+                {
+                    throw body.getConnectionException(AMQConstant.COMMAND_INVALID,
+                                                      "Error creating exchange '"
+                                                      + exchangeName
+                                                      + "': "
+                                                      + e.getMessage(),
+                                                      _connection.getMethodRegistry());
+                }
+            }
+        }
+
+        if(!body.getNowait())
+        {
+            MethodRegistry methodRegistry = _connection.getMethodRegistry();
+            AMQMethodBody responseBody = methodRegistry.createExchangeDeclareOkBody();
+            channel.sync();
+            _connection.writeFrame(responseBody.generateFrame(channelId));
+        }
+        return true;
+    }
+
+    public boolean dispatchExchangeDelete(ExchangeDeleteBody body, int channelId) throws AMQException
+    {
+        VirtualHostImpl virtualHost = _connection.getVirtualHost();
+        final AMQChannel channel = _connection.getChannel(channelId);
+        if (channel == null)
+        {
+            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+        }
+        channel.sync();
+        try
+        {
+
+            if(isDefaultExchange(body.getExchange()))
+            {
+                throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+                                                  "Default Exchange cannot be deleted",
+                                                  _connection.getMethodRegistry());
+            }
+
+            final String exchangeName = body.getExchange().toString();
+
+            final ExchangeImpl exchange = virtualHost.getExchange(exchangeName);
+            if(exchange == null)
+            {
+                throw body.getChannelException(AMQConstant.NOT_FOUND, "No such exchange: " + body.getExchange(),
+                                               _connection.getMethodRegistry());
+            }
+
+            virtualHost.removeExchange(exchange, !body.getIfUnused());
+
+            ExchangeDeleteOkBody responseBody = _connection.getMethodRegistry().createExchangeDeleteOkBody();
+
+            _connection.writeFrame(responseBody.generateFrame(channelId));
+        }
+
+        catch (ExchangeIsAlternateException e)
+        {
+            throw body.getChannelException(AMQConstant.NOT_ALLOWED, "Exchange in use as an alternate exchange",
+                                           _connection.getMethodRegistry());
+
+        }
+        catch (RequiredExchangeException e)
+        {
+            throw body.getChannelException(AMQConstant.NOT_ALLOWED,
+                                           "Exchange '" + body.getExchange() + "' cannot be deleted",
+                                           _connection.getMethodRegistry());
+        }
+        catch (AccessControlException e)
+        {
+            throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+                                              e.getMessage(),
+                                              _connection.getMethodRegistry());
+        }
+        return true;
+    }
+
+    private boolean isDefaultExchange(final AMQShortString exchangeName)
+    {
+        return exchangeName == null || exchangeName.equals(AMQShortString.EMPTY_STRING);
+    }
+
+    public boolean dispatchQueueBind(QueueBindBody body, int channelId) throws AMQException
+    {
+        VirtualHostImpl virtualHost = _connection.getVirtualHost();
+        AMQChannel channel = _connection.getChannel(channelId);
+
+        if (channel == null)
+        {
+            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+        }
+
+        final AMQQueue queue;
+        final AMQShortString routingKey;
+
+        final AMQShortString queueName = body.getQueue();
+
+        if (queueName == null)
+        {
+
+            queue = channel.getDefaultQueue();
+
+            if (queue == null)
+            {
+                throw body.getChannelException(AMQConstant.NOT_FOUND,
+                                               "No default queue defined on channel and queue was null",
+                                               _connection.getMethodRegistry());
+            }
+
+            if (body.getRoutingKey() == null)
+            {
+                routingKey = AMQShortString.valueOf(queue.getName());
+            }
+            else
+            {
+                routingKey = body.getRoutingKey().intern();
+            }
+        }
+        else
+        {
+            queue = virtualHost.getQueue(queueName.toString());
+            routingKey = body.getRoutingKey() == null ? AMQShortString.EMPTY_STRING : body.getRoutingKey().intern();
+        }
+
+        if (queue == null)
+        {
+            throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + queueName + " does not exist.",
+                                           _connection.getMethodRegistry());
+        }
+
+        if(isDefaultExchange(body.getExchange()))
+        {
+            throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+                                              "Cannot bind the queue " + queueName + " to the default exchange",
+                                              _connection.getMethodRegistry());
+        }
+
+        final String exchangeName = body.getExchange().toString();
+
+        final ExchangeImpl exch = virtualHost.getExchange(exchangeName);
+        if (exch == null)
+        {
+            throw body.getChannelException(AMQConstant.NOT_FOUND, "Exchange " + exchangeName + " does not exist.",
+                                           _connection.getMethodRegistry());
+        }
+
+
+        try
+        {
+
+            Map<String,Object> arguments = FieldTable.convertToMap(body.getArguments());
+            String bindingKey = String.valueOf(routingKey);
+
+            if (!exch.isBound(bindingKey, arguments, queue))
+            {
+
+                if(!exch.addBinding(bindingKey, queue, arguments) && ExchangeDefaults.TOPIC_EXCHANGE_CLASS.equals(exch.getType()))
+                {
+                    exch.replaceBinding(bindingKey, queue, arguments);
+                }
+            }
+        }
+        catch (AccessControlException e)
+        {
+            throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+                                              e.getMessage(),
+                                              _connection.getMethodRegistry());
+        }
+
+        if (_logger.isInfoEnabled())
+        {
+            _logger.info("Binding queue " + queue + " to exchange " + exch + " with routing key " + routingKey);
+        }
+        if (!body.getNowait())
+        {
+            channel.sync();
+            MethodRegistry methodRegistry = _connection.getMethodRegistry();
+            AMQMethodBody responseBody = methodRegistry.createQueueBindOkBody();
+            _connection.writeFrame(responseBody.generateFrame(channelId));
+
+        }
+        return true;
+    }
+
+    public boolean dispatchQueueDeclare(QueueDeclareBody body, int channelId) throws AMQException
+    {
+        final AMQSessionModel session = _connection.getChannel(channelId);
+        VirtualHostImpl virtualHost = _connection.getVirtualHost();
+
+        final AMQShortString queueName;
+
+        // if we aren't given a queue name, we create one which we return to the client
+        if ((body.getQueue() == null) || (body.getQueue().length() == 0))
+        {
+            queueName = new AMQShortString("tmp_" + UUID.randomUUID());
+        }
+        else
+        {
+            queueName = body.getQueue().intern();
+        }
+
+        AMQQueue queue;
+
+        //TODO: do we need to check that the queue already exists with exactly the same "configuration"?
+
+        AMQChannel channel = _connection.getChannel(channelId);
+
+        if (channel == null)
+        {
+            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+        }
+
+        if(body.getPassive())
+        {
+            queue = virtualHost.getQueue(queueName.toString());
+            if (queue == null)
+            {
+                String msg = "Queue: " + queueName + " not found on VirtualHost(" + virtualHost + ").";
+                throw body.getChannelException(AMQConstant.NOT_FOUND, msg, _connection.getMethodRegistry());
+            }
+            else
+            {
+                if (!queue.verifySessionAccess(channel))
+                {
+                    throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+                                                      "Queue "
+                                                      + queue.getName()
+                                                      + " is exclusive, but not created on this Connection.",
+                                                      _connection.getMethodRegistry());
+                }
+
+                //set this as the default queue on the channel:
+                channel.setDefaultQueue(queue);
+            }
+        }
+        else
+        {
+
+            try
+            {
+
+                queue = createQueue(channel, queueName, body, virtualHost, _connection);
+
+            }
+            catch(QueueExistsException qe)
+            {
+
+                queue = qe.getExistingQueue();
+
+                if (!queue.verifySessionAccess(channel))
+                {
+                    throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+                                                      "Queue "
+                                                      + queue.getName()
+                                                      + " is exclusive, but not created on this Connection.",
+                                                      _connection.getMethodRegistry());
+                }
+                else if(queue.isExclusive() != body.getExclusive())
+                {
+
+                    throw body.getChannelException(AMQConstant.ALREADY_EXISTS,
+                                                   "Cannot re-declare queue '"
+                                                   + queue.getName()
+                                                   + "' with different exclusivity (was: "
+                                                   + queue.isExclusive()
+                                                   + " requested "
+                                                   + body.getExclusive()
+                                                   + ")",
+                                                   _connection.getMethodRegistry());
+                }
+                else if((body.getAutoDelete() && queue.getLifetimePolicy() != LifetimePolicy.DELETE_ON_NO_OUTBOUND_LINKS)
+                    || (!body.getAutoDelete() && queue.getLifetimePolicy() != ((body.getExclusive() && !body.getDurable()) ? LifetimePolicy.DELETE_ON_CONNECTION_CLOSE : LifetimePolicy.PERMANENT)))
+                {
+                    throw body.getChannelException(AMQConstant.ALREADY_EXISTS,
+                                                   "Cannot re-declare queue '"
+                                                   + queue.getName()
+                                                   + "' with different lifetime policy (was: "
+                                                   + queue.getLifetimePolicy()
+                                                   + " requested autodelete: "
+                                                   + body.getAutoDelete()
+                                                   + ")",
+                                                   _connection.getMethodRegistry());
+                }
+                else if(queue.isDurable() != body.getDurable())
+                {
+                    throw body.getChannelException(AMQConstant.ALREADY_EXISTS,
+                                                   "Cannot re-declare queue '"
+                                                   + queue.getName()
+                                                   + "' with different durability (was: "
+                                                   + queue.isDurable()
+                                                   + " requested "
+                                                   + body.getDurable()
+                                                   + ")",
+                                                   _connection.getMethodRegistry());
+                }
+
+            }
+            catch (AccessControlException e)
+            {
+                throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+                                                  e.getMessage(),
+                                                  _connection.getMethodRegistry());
+            }
+
+            //set this as the default queue on the channel:
+            channel.setDefaultQueue(queue);
+        }
+
+        if (!body.getNowait())
+        {
+            channel.sync();
+            MethodRegistry methodRegistry = _connection.getMethodRegistry();
+            QueueDeclareOkBody responseBody =
+                    methodRegistry.createQueueDeclareOkBody(queueName,
+                                                            queue.getQueueDepthMessages(),
+                                                            queue.getConsumerCount());
+            _connection.writeFrame(responseBody.generateFrame(channelId));
+
+            _logger.info("Queue " + queueName + " declared successfully");
+        }
+        return true;
+    }
+
+    protected AMQQueue createQueue(final AMQChannel channel, final AMQShortString queueName,
+                                   QueueDeclareBody body,
+                                   final VirtualHostImpl virtualHost,
+                                   final AMQProtocolSession session)
+            throws AMQException, QueueExistsException
+    {
+
+        final boolean durable = body.getDurable();
+        final boolean autoDelete = body.getAutoDelete();
+        final boolean exclusive = body.getExclusive();
+
+
+        Map<String, Object> attributes =
+                QueueArgumentsConverter.convertWireArgsToModel(FieldTable.convertToMap(body.getArguments()));
+        final String queueNameString = AMQShortString.toString(queueName);
+        attributes.put(Queue.NAME, queueNameString);
+        attributes.put(Queue.ID, UUID.randomUUID());
+        attributes.put(Queue.DURABLE, durable);
+
+        LifetimePolicy lifetimePolicy;
+        ExclusivityPolicy exclusivityPolicy;
+
+        if(exclusive)
+        {
+            lifetimePolicy = autoDelete
+                    ? LifetimePolicy.DELETE_ON_NO_OUTBOUND_LINKS
+                    : durable ? LifetimePolicy.PERMANENT : LifetimePolicy.DELETE_ON_CONNECTION_CLOSE;
+            exclusivityPolicy = durable ? ExclusivityPolicy.CONTAINER : ExclusivityPolicy.CONNECTION;
+        }
+        else
+        {
+            lifetimePolicy = autoDelete ? LifetimePolicy.DELETE_ON_NO_OUTBOUND_LINKS : LifetimePolicy.PERMANENT;
+            exclusivityPolicy = ExclusivityPolicy.NONE;
+        }
+
+        attributes.put(Queue.EXCLUSIVE, exclusivityPolicy);
+        attributes.put(Queue.LIFETIME_POLICY, lifetimePolicy);
+
+
+        final AMQQueue queue = virtualHost.createQueue(attributes);
+
+        return queue;
+    }
+
+    public boolean dispatchQueueDelete(QueueDeleteBody body, int channelId) throws AMQException
+    {
+        VirtualHostImpl virtualHost = _connection.getVirtualHost();
+
+        AMQChannel channel = _connection.getChannel(channelId);
+
+        if (channel == null)
+        {
+            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+        }
+        channel.sync();
+        AMQQueue queue;
+        if (body.getQueue() == null)
+        {
+
+            //get the default queue on the channel:
+            queue = channel.getDefaultQueue();
+        }
+        else
+        {
+            queue = virtualHost.getQueue(body.getQueue().toString());
+        }
+
+        if (queue == null)
+        {
+            throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + body.getQueue() + " does not exist.",
+                                           _connection.getMethodRegistry());
+
+        }
+        else
+        {
+            if (body.getIfEmpty() && !queue.isEmpty())
+            {
+                throw body.getChannelException(AMQConstant.IN_USE, "Queue: " + body.getQueue() + " is not empty.",
+                                               _connection.getMethodRegistry());
+            }
+            else if (body.getIfUnused() && !queue.isUnused())
+            {
+                // TODO - Error code
+                throw body.getChannelException(AMQConstant.IN_USE, "Queue: " + body.getQueue() + " is still used.",
+                                               _connection.getMethodRegistry());
+            }
+            else
+            {
+                if (!queue.verifySessionAccess(channel))
+                {
+                    throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+                                                      "Queue "
+                                                      + queue.getName()
+                                                      + " is exclusive, but not created on this Connection.",
+                                                      _connection.getMethodRegistry());
+                }
+
+                int purged = 0;
+                try
+                {
+                    purged = virtualHost.removeQueue(queue);
+                }
+                catch (AccessControlException e)
+                {
+                    throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+                                                      e.getMessage(),
+                                                      _connection.getMethodRegistry());
+                }
+
+                MethodRegistry methodRegistry = _connection.getMethodRegistry();
+                QueueDeleteOkBody responseBody = methodRegistry.createQueueDeleteOkBody(purged);
+                _connection.writeFrame(responseBody.generateFrame(channelId));
+            }
+        }
+        return true;
+    }
+
+    public boolean dispatchQueuePurge(QueuePurgeBody body, int channelId) throws AMQException
+    {
+        VirtualHostImpl virtualHost = _connection.getVirtualHost();
+
+        AMQChannel channel = _connection.getChannel(channelId);
+        if (channel == null)
+        {
+            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+        }
+        AMQQueue queue;
+        if(body.getQueue() == null)
+        {
+
+           //get the default queue on the channel:
+           queue = channel.getDefaultQueue();
+
+            if(queue == null)
+            {
+                throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+                                                  "No queue specified.",
+                                                  _connection.getMethodRegistry());
+            }
+        }
+        else
+        {
+            queue = virtualHost.getQueue(body.getQueue().toString());
+        }
+
+        if(queue == null)
+        {
+            throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + body.getQueue() + " does not exist.",
+                                           _connection.getMethodRegistry());
+        }
+        else
+        {
+                if (!queue.verifySessionAccess(channel))
+                {
+                    throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+                                                      "Queue is exclusive, but not created on this Connection.",
+                                                      _connection.getMethodRegistry());
+                }
+
+            long purged = 0;
+            try
+            {
+                purged = queue.clearQueue();
+            }
+            catch (AccessControlException e)
+            {
+                throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+                                                  e.getMessage(),
+                                                  _connection.getMethodRegistry());
+            }
+
+
+            if(!body.getNowait())
+                {
+                    channel.sync();
+                    MethodRegistry methodRegistry = _connection.getMethodRegistry();
+                    AMQMethodBody responseBody = methodRegistry.createQueuePurgeOkBody(purged);
+                    _connection.writeFrame(responseBody.generateFrame(channelId));
+
+                }
+        }
+        return true;
+    }
+
+
+    public boolean dispatchTxCommit(TxCommitBody body, final int channelId) throws AMQException
+    {
+        try
+        {
+            if (_logger.isDebugEnabled())
+            {
+                _logger.debug("Commit received on channel " + channelId);
+            }
+            AMQChannel channel = _connection.getChannel(channelId);
+
+            if (channel == null)
+            {
+                throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+            }
+            channel.commit(new Runnable()
+            {
+
+                @Override
+                public void run()
+                {
+                    MethodRegistry methodRegistry = _connection.getMethodRegistry();
+                    AMQMethodBody responseBody = methodRegistry.createTxCommitOkBody();
+                    _connection.writeFrame(responseBody.generateFrame(channelId));
+                }
+            }, true);
+
+
+
+        }
+        catch (AMQException e)
+        {
+            throw body.getChannelException(e.getErrorCode(), "Failed to commit: " + e.getMessage(),
+                                           _connection.getMethodRegistry());
+        }
+        return true;
+    }
+
+    public boolean dispatchTxRollback(TxRollbackBody body, final int channelId) throws AMQException
+    {
+        try
+        {
+            AMQChannel channel = _connection.getChannel(channelId);
+
+            if (channel == null)
+            {
+                throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+            }
+
+
+
+            final MethodRegistry methodRegistry = _connection.getMethodRegistry();
+            final AMQMethodBody responseBody = methodRegistry.createTxRollbackOkBody();
+
+            Runnable task = new Runnable()
+            {
+
+                public void run()
+                {
+                    _connection.writeFrame(responseBody.generateFrame(channelId));
+                }
+            };
+
+            channel.rollback(task);
+
+            //Now resend all the unacknowledged messages back to the original subscribers.
+            //(Must be done after the TxnRollback-ok response).
+            // Why, are we not allowed to send messages back to client before the ok method?
+            channel.resend();
+
+        }
+        catch (AMQException e)
+        {
+            throw body.getChannelException(e.getErrorCode(), "Failed to rollback: " + e.getMessage(),
+                                           _connection.getMethodRegistry());
+        }
+        return true;
+    }
+
+    public boolean dispatchTxSelect(TxSelectBody body, int channelId) throws AMQException
+    {
+        AMQChannel channel = _connection.getChannel(channelId);
+
+        if (channel == null)
+        {
+            throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+        }
+
+        channel.setLocalTransactional();
+
+        MethodRegistry methodRegistry = _connection.getMethodRegistry();
+        TxSelectOkBody responseBody = methodRegistry.createTxSelectOkBody();
+        _connection.writeFrame(responseBody.generateFrame(channelId));
+        return true;
+    }
+
+    public boolean dispatchBasicRecoverSync(BasicRecoverSyncBody body, int channelId) throws AMQException
+    {
+        final AMQProtocolSession<?> connection = getConnection();
+
+        _logger.debug("Recover received on protocol session " + connection + " and channel " + channelId);
+        AMQChannel channel = connection.getChannel(channelId);
+
+
+        if (channel == null)
+        {
+            throw body.getChannelNotFoundException(channelId, connection.getMethodRegistry());
+        }
+        channel.sync();
+        channel.resend();
+
+        MethodRegistry methodRegistry = connection.getMethodRegistry();
+        AMQMethodBody recoverOk = methodRegistry.createBasicRecoverSyncOkBody();
+        connection.writeFrame(recoverOk.generateFrame(channelId));
+
+        return true;
+    }
+
+    public boolean dispatchBasicRecoverSyncOk(BasicRecoverSyncOkBody body, int channelId) throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+    @Override
+    public boolean dispatchChannelAlert(final ChannelAlertBody body, final int channelId)
+            throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+    public boolean dispatchQueueUnbindOk(QueueUnbindOkBody body, int channelId) throws AMQException
+    {
+        throw new UnexpectedMethodException(body);
+    }
+
+    public boolean dispatchQueueUnbind(QueueUnbindBody body, int channelId) throws AMQException
+    {
+        final AMQProtocolSession<?> connection = getConnection();
+
+        if (ProtocolVersion.v8_0.equals(connection.getProtocolVersion()))
+        {
+            // 0-8 does not support QueueUnbind
+            throw new AMQException(AMQConstant.COMMAND_INVALID, "QueueUnbind not present in AMQP version: " + connection.getProtocolVersion(), null);
+        }
+
+        VirtualHostImpl virtualHost = connection.getVirtualHost();
+
+        final AMQQueue queue;
+        final AMQShortString routingKey;
+
+
+        AMQChannel channel = connection.getChannel(channelId);
+        if (channel == null)
+        {
+            throw body.getChannelNotFoundException(channelId, connection.getMethodRegistry());
+        }
+
+        if (body.getQueue() == null)
+        {
+
+            queue = channel.getDefaultQueue();
+
+            if (queue == null)
+            {
+                throw body.getChannelException(AMQConstant.NOT_FOUND,
+                                               "No default queue defined on channel and queue was null",
+                                               connection.getMethodRegistry());
+            }
+
+            routingKey = body.getRoutingKey() == null ? null : body.getRoutingKey().intern(false);
+
+        }
+        else
+        {
+            queue = virtualHost.getQueue(body.getQueue().toString());
+            routingKey = body.getRoutingKey() == null ? null : body.getRoutingKey().intern(false);
+        }
+
+        if (queue == null)
+        {
+            throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + body.getQueue() + " does not exist.",
+                                           connection.getMethodRegistry());
+        }
+
+        if(isDefaultExchange(body.getExchange()))
+        {
+            throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+                                              "Cannot unbind the queue "
+                                              + queue.getName()
+                                              + " from the default exchange", connection.getMethodRegistry());
+        }
+
+        final ExchangeImpl exch = virtualHost.getExchange(body.getExchange() == null ? null : body.getExchange().toString());
+        if (exch == null)
+        {
+            throw body.getChannelException(AMQConstant.NOT_FOUND, "Exchange " + body.getExchange() + " does not exist.",
+                                           connection.getMethodRegistry());
+        }
+
+        if(!exch.hasBinding(String.valueOf(routingKey), queue))
+        {
+            throw body.getChannelException(AMQConstant.NOT_FOUND, "No such binding", connection.getMethodRegistry());
+        }
+        else
+        {
+            try
+            {
+                exch.deleteBinding(String.valueOf(routingKey), queue);
+            }
+            catch (AccessControlException e)
+            {
+                throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+                                                  e.getMessage(),
+                                                  connection.getMethodRegistry());
+            }
+        }
+
+
+        if (_logger.isInfoEnabled())
+        {
+            _logger.info("Binding queue " + queue + " to exchange " + exch + " with routing key " + routingKey);
+        }
+
+
+        final AMQMethodBody responseBody = connection.getMethodRegistry().createQueueUnbindOkBody();
+        channel.sync();
+        connection.writeFrame(responseBody.generateFrame(channelId));
+        return true;
+    }
+
+}
diff --git a/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ServerMethodProcessor.java b/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ServerMethodProcessor.java
new file mode 100644
index 0000000..40e1af1
--- /dev/null
+++ b/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ServerMethodProcessor.java
@@ -0,0 +1,957 @@
+/*
+ *
+ * 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.server.protocol.v0_8;
+
+import java.security.PrivilegedAction;
+
+import javax.security.auth.Subject;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.framing.*;
+import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.security.SubjectCreator;
+import org.apache.qpid.server.security.auth.SubjectAuthenticationResult;
+
+public class ServerMethodProcessor implements MethodProcessor
+{
+    private static final Logger LOGGER = Logger.getLogger(ServerMethodProcessor.class);
+
+
+    private static interface ChannelAction
+    {
+        void onChannel(ChannelMethodProcessor channel);
+    }
+
+    private ProtocolVersion _protocolVersion;
+    private ServerMethodDispatcherImpl _dispatcher;
+    private AMQProtocolEngine _connection;
+
+    public ServerMethodProcessor(final ProtocolVersion protocolVersion)
+    {
+        _protocolVersion = protocolVersion;
+    }
+
+
+    private void processChannelMethod(int channelId, final ChannelAction action)
+    {
+        final AMQChannel channel = _connection.getChannel(channelId);
+        if (channel == null)
+        {
+            // TODO throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+        }
+        else
+        {
+            Subject.doAs(channel.getSubject(), new PrivilegedAction<Void>()
+            {
+                @Override
+                public Void run()
+                {
+                    action.onChannel(channel.getMethodProcessor());
+                    return null;
+                }
+            });
+        }
+
+    }
+
+    @Override
+    public void receiveConnectionStart(final short versionMajor,
+                                       final short versionMinor,
+                                       final FieldTable serverProperties,
+                                       final byte[] mechanisms,
+                                       final byte[] locales)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(0,
+                                          new ConnectionStartBody(versionMajor,
+                                                                  versionMinor,
+                                                                  serverProperties,
+                                                                  mechanisms,
+                                                                  locales));
+        }
+        _connection.closeConnection(AMQConstant.COMMAND_INVALID, "Unexpected method received:  ConnectionStart", 0,
+                                    ConnectionStartBody.CLASS_ID, ConnectionStartBody.METHOD_ID);
+
+    }
+
+    @Override
+    public void receiveConnectionStartOk(final FieldTable clientProperties,
+                                         final AMQShortString mechanism,
+                                         final byte[] response,
+                                         final AMQShortString locale)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(0, new ConnectionStartOkBody(clientProperties, mechanism, response, locale));
+        }
+
+        Broker<?> broker = _connection.getBroker();
+
+        SubjectCreator subjectCreator = _connection.getSubjectCreator();
+        SaslServer ss = null;
+        try
+        {
+            ss = subjectCreator.createSaslServer(String.valueOf(mechanism),
+                                                 _connection.getLocalFQDN(),
+                                                 _connection.getPeerPrincipal());
+
+            if (ss == null)
+            {
+                _connection.closeConnection(AMQConstant.RESOURCE_ERROR,
+                                                  "Unable to create SASL Server:" + mechanism, 0,
+                                                  ConnectionStartOkBody.CLASS_ID,
+                                                  ConnectionStartOkBody.METHOD_ID);
+            }
+            else
+            {
+                _connection.setSaslServer(ss);
+
+                final SubjectAuthenticationResult authResult = subjectCreator.authenticate(ss, response);
+                //save clientProperties
+                _connection.setClientProperties(clientProperties);
+
+                MethodRegistry methodRegistry = _connection.getMethodRegistry();
+
+                switch (authResult.getStatus())
+                {
+                    case ERROR:
+                        Exception cause = authResult.getCause();
+
+                        LOGGER.info("Authentication failed:" + (cause == null ? "" : cause.getMessage()));
+
+                        _connection.closeConnection(AMQConstant.NOT_ALLOWED,
+                                                    AMQConstant.NOT_ALLOWED.getName().toString(), 0,
+                                                    ConnectionStartOkBody.CLASS_ID,
+                                                    ConnectionStartOkBody.METHOD_ID);
+
+                        disposeSaslServer();
+                        break;
+
+                    case SUCCESS:
+                        if (LOGGER.isInfoEnabled())
+                        {
+                            LOGGER.info("Connected as: " + authResult.getSubject());
+                        }
+                        _connection.setAuthorizedSubject(authResult.getSubject());
+
+                        int frameMax = broker.getContextValue(Integer.class, Broker.BROKER_FRAME_SIZE);
+
+                        if (frameMax <= 0)
+                        {
+                            frameMax = Integer.MAX_VALUE;
+                        }
+
+                        ConnectionTuneBody
+                                tuneBody =
+                                methodRegistry.createConnectionTuneBody(broker.getConnection_sessionCountLimit(),
+                                                                        frameMax,
+                                                                        broker.getConnection_heartBeatDelay());
+                        _connection.writeFrame(tuneBody.generateFrame(0));
+                        break;
+                    case CONTINUE:
+                        ConnectionSecureBody
+                                secureBody = methodRegistry.createConnectionSecureBody(authResult.getChallenge());
+                        _connection.writeFrame(secureBody.generateFrame(0));
+                }
+            }
+        }
+        catch (SaslException e)
+        {
+            disposeSaslServer();
+
+            _connection.closeConnection(AMQConstant.RESOURCE_ERROR, "SASL error:  " + e.getMessage(), 0,
+                                        ConnectionStartOkBody.CLASS_ID, ConnectionStartOkBody.METHOD_ID);
+        }
+
+    }
+
+    @Override
+    public void receiveTxSelect(final int channelId)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, TxSelectBody.INSTANCE);
+        }
+
+    }
+
+    @Override
+    public void receiveTxSelectOk(final int channelId)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, TxSelectOkBody.INSTANCE);
+        }
+
+    }
+
+    @Override
+    public void receiveTxCommit(final int channelId)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, TxCommitBody.INSTANCE);
+        }
+
+    }
+
+    @Override
+    public void receiveTxCommitOk(final int channelId)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, TxCommitOkBody.INSTANCE);
+        }
+
+    }
+
+    @Override
+    public void receiveTxRollback(final int channelId)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, TxRollbackBody.INSTANCE);
+        }
+
+    }
+
+    @Override
+    public void receiveTxRollbackOk(final int channelId)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, TxRollbackOkBody.INSTANCE);
+        }
+
+    }
+
+    @Override
+    public void receiveConnectionSecure(final byte[] challenge)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(0, new ConnectionSecureBody(challenge));
+        }
+
+    }
+
+    @Override
+    public void receiveConnectionSecureOk(final byte[] response)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(0, new ConnectionSecureOkBody(response));
+        }
+
+    }
+
+    @Override
+    public void receiveConnectionTune(final int channelMax, final long frameMax, final int heartbeat)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(0, new ConnectionTuneBody(channelMax, frameMax, heartbeat));
+        }
+
+    }
+
+    @Override
+    public void receiveConnectionTuneOk(final int channelMax, final long frameMax, final int heartbeat)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(0, new ConnectionTuneOkBody(channelMax, frameMax, heartbeat));
+        }
+
+    }
+
+    @Override
+    public void receiveConnectionOpen(final AMQShortString virtualHost,
+                                      final AMQShortString capabilities,
+                                      final boolean insist)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(0, new ConnectionOpenBody(virtualHost, capabilities, insist));
+        }
+
+    }
+
+    @Override
+    public void receiveConnectionOpenOk(final AMQShortString knownHosts)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(0, new ConnectionOpenOkBody(knownHosts));
+        }
+
+    }
+
+    @Override
+    public void receiveConnectionRedirect(final AMQShortString host, final AMQShortString knownHosts)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(0, new ConnectionRedirectBody(getProtocolVersion(), host, knownHosts));
+        }
+
+    }
+
+    @Override
+    public void receiveConnectionClose(final int replyCode,
+                                       final AMQShortString replyText,
+                                       final int classId,
+                                       final int methodId)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(0,
+                                          new ConnectionCloseBody(getProtocolVersion(),
+                                                                  replyCode,
+                                                                  replyText,
+                                                                  classId,
+                                                                  methodId));
+        }
+
+    }
+
+    @Override
+    public void receiveConnectionCloseOk()
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(0, ProtocolVersion.v8_0.equals(getProtocolVersion())
+                    ? ConnectionCloseOkBody.CONNECTION_CLOSE_OK_0_8
+                    : ConnectionCloseOkBody.CONNECTION_CLOSE_OK_0_9);
+        }
+    }
+
+    @Override
+    public void receiveChannelOpen(final int channelId)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new ChannelOpenBody());
+        }
+
+    }
+
+    @Override
+    public void receiveChannelOpenOk(final int channelId)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, ProtocolVersion.v8_0.equals(getProtocolVersion())
+                    ? ChannelOpenOkBody.INSTANCE_0_8
+                    : ChannelOpenOkBody.INSTANCE_0_9);
+        }
+    }
+
+    @Override
+    public void receiveChannelFlow(final int channelId, final boolean active)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new ChannelFlowBody(active));
+        }
+
+    }
+
+    @Override
+    public void receiveChannelFlowOk(final int channelId, final boolean active)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new ChannelFlowOkBody(active));
+        }
+
+    }
+
+    @Override
+    public void receiveChannelAlert(final int channelId,
+                                    final int replyCode,
+                                    final AMQShortString replyText,
+                                    final FieldTable details)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new ChannelAlertBody(replyCode, replyText, details));
+        }
+
+    }
+
+    @Override
+    public void receiveChannelClose(final int channelId,
+                                    final int replyCode,
+                                    final AMQShortString replyText,
+                                    final int classId,
+                                    final int methodId)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new ChannelCloseBody(replyCode, replyText, classId, methodId));
+        }
+
+    }
+
+    @Override
+    public void receiveChannelCloseOk(final int channelId)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, ChannelCloseOkBody.INSTANCE);
+        }
+
+    }
+
+    @Override
+    public void receiveAccessRequest(final int channelId,
+                                     final AMQShortString realm,
+                                     final boolean exclusive,
+                                     final boolean passive,
+                                     final boolean active,
+                                     final boolean write,
+                                     final boolean read)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame =
+                    new AMQFrame(channelId, new AccessRequestBody(realm, exclusive, passive, active, write, read));
+        }
+
+    }
+
+    @Override
+    public void receiveAccessRequestOk(final int channelId, final int ticket)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new AccessRequestOkBody(ticket));
+        }
+
+    }
+
+    @Override
+    public void receiveExchangeDeclare(final int channelId,
+                                       final AMQShortString exchange,
+                                       final AMQShortString type,
+                                       final boolean passive,
+                                       final boolean durable,
+                                       final boolean autoDelete,
+                                       final boolean internal,
+                                       final boolean nowait, final FieldTable arguments)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId,
+                                          new ExchangeDeclareBody(0,
+                                                                  exchange,
+                                                                  type,
+                                                                  passive,
+                                                                  durable,
+                                                                  autoDelete,
+                                                                  internal,
+                                                                  nowait,
+                                                                  arguments));
+        }
+
+    }
+
+    @Override
+    public void receiveExchangeDeclareOk(final int channelId)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new ExchangeDeclareOkBody());
+        }
+
+    }
+
+    @Override
+    public void receiveExchangeDelete(final int channelId,
+                                      final AMQShortString exchange,
+                                      final boolean ifUnused,
+                                      final boolean nowait)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new ExchangeDeleteBody(0, exchange, ifUnused, nowait));
+        }
+
+    }
+
+    @Override
+    public void receiveExchangeDeleteOk(final int channelId)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new ExchangeDeleteOkBody());
+        }
+
+    }
+
+    @Override
+    public void receiveExchangeBound(final int channelId,
+                                     final AMQShortString exchange,
+                                     final AMQShortString routingKey,
+                                     final AMQShortString queue)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new ExchangeBoundBody(exchange, routingKey, queue));
+        }
+
+    }
+
+    @Override
+    public void receiveExchangeBoundOk(final int channelId, final int replyCode, final AMQShortString replyText)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new ExchangeBoundOkBody(replyCode, replyText));
+        }
+
+    }
+
+    @Override
+    public void receiveQueueBindOk(final int channelId)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new QueueBindOkBody());
+        }
+
+    }
+
+    @Override
+    public void receiveQueueUnbindOk(final int channelId)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new QueueUnbindOkBody());
+        }
+
+    }
+
+    @Override
+    public void receiveQueueDeclare(final int channelId,
+                                    final AMQShortString queue,
+                                    final boolean passive,
+                                    final boolean durable,
+                                    final boolean exclusive,
+                                    final boolean autoDelete,
+                                    final boolean nowait,
+                                    final FieldTable arguments)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId,
+                                          new QueueDeclareBody(0,
+                                                               queue,
+                                                               passive,
+                                                               durable,
+                                                               exclusive,
+                                                               autoDelete,
+                                                               nowait,
+                                                               arguments));
+        }
+
+    }
+
+    @Override
+    public void receiveQueueDeclareOk(final int channelId,
+                                      final AMQShortString queue,
+                                      final long messageCount,
+                                      final long consumerCount)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new QueueDeclareOkBody(queue, messageCount, consumerCount));
+        }
+
+    }
+
+    @Override
+    public void receiveQueueBind(final int channelId,
+                                 final AMQShortString queue,
+                                 final AMQShortString exchange,
+                                 final AMQShortString bindingKey,
+                                 final boolean nowait,
+                                 final FieldTable arguments)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame =
+                    new AMQFrame(channelId, new QueueBindBody(0, queue, exchange, bindingKey, nowait, arguments));
+        }
+
+    }
+
+    @Override
+    public void receiveQueuePurge(final int channelId, final AMQShortString queue, final boolean nowait)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new QueuePurgeBody(0, queue, nowait));
+        }
+
+    }
+
+    @Override
+    public void receiveQueuePurgeOk(final int channelId, final long messageCount)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new QueuePurgeOkBody(messageCount));
+        }
+
+    }
+
+    @Override
+    public void receiveQueueDelete(final int channelId,
+                                   final AMQShortString queue,
+                                   final boolean ifUnused,
+                                   final boolean ifEmpty,
+                                   final boolean nowait)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new QueueDeleteBody(0, queue, ifUnused, ifEmpty, nowait));
+        }
+
+    }
+
+    @Override
+    public void receiveQueueDeleteOk(final int channelId, final long messageCount)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new QueueDeleteOkBody(messageCount));
+        }
+
+    }
+
+    @Override
+    public void receiveQueueUnbind(final int channelId,
+                                   final AMQShortString queue,
+                                   final AMQShortString exchange,
+                                   final AMQShortString bindingKey,
+                                   final FieldTable arguments)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new QueueUnbindBody(0, queue, exchange, bindingKey, arguments));
+        }
+
+    }
+
+    @Override
+    public void receiveBasicRecoverSyncOk(final int channelId)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new BasicRecoverSyncOkBody(getProtocolVersion()));
+        }
+
+    }
+
+    @Override
+    public void receiveBasicRecover(final int channelId, final boolean requeue, final boolean sync)
+    {
+        if (ProtocolVersion.v8_0.equals(getProtocolVersion()) || !sync)
+        {
+            if (LOGGER.isDebugEnabled())
+            {
+                AMQFrame frame = new AMQFrame(channelId, new BasicRecoverBody(requeue));
+            }
+
+        }
+        else
+        {
+            if (LOGGER.isDebugEnabled())
+            {
+                AMQFrame frame = new AMQFrame(channelId, new BasicRecoverSyncBody(getProtocolVersion(), requeue));
+            }
+
+        }
+    }
+
+    @Override
+    public void receiveBasicQos(final int channelId,
+                                final long prefetchSize,
+                                final int prefetchCount,
+                                final boolean global)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new BasicQosBody(prefetchSize, prefetchCount, global));
+        }
+
+    }
+
+    @Override
+    public void receiveBasicQosOk(final int channelId)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new BasicQosOkBody());
+        }
+
+    }
+
+    @Override
+    public void receiveBasicConsume(final int channelId,
+                                    final AMQShortString queue,
+                                    final AMQShortString consumerTag,
+                                    final boolean noLocal,
+                                    final boolean noAck,
+                                    final boolean exclusive,
+                                    final boolean nowait,
+                                    final FieldTable arguments)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId,
+                                          new BasicConsumeBody(0,
+                                                               queue,
+                                                               consumerTag,
+                                                               noLocal,
+                                                               noAck,
+                                                               exclusive,
+                                                               nowait,
+                                                               arguments));
+        }
+
+    }
+
+    @Override
+    public void receiveBasicConsumeOk(final int channelId, final AMQShortString consumerTag)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new BasicConsumeOkBody(consumerTag));
+        }
+
+    }
+
+    @Override
+    public void receiveBasicCancel(final int channelId, final AMQShortString consumerTag, final boolean noWait)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new BasicCancelBody(consumerTag, noWait));
+        }
+
+    }
+
+    @Override
+    public void receiveBasicCancelOk(final int channelId, final AMQShortString consumerTag)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new BasicCancelOkBody(consumerTag));
+        }
+
+    }
+
+    @Override
+    public void receiveBasicPublish(final int channelId,
+                                    final AMQShortString exchange,
+                                    final AMQShortString routingKey,
+                                    final boolean mandatory,
+                                    final boolean immediate)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame =
+                    new AMQFrame(channelId, new BasicPublishBody(0, exchange, routingKey, mandatory, immediate));
+        }
+
+    }
+
+    @Override
+    public void receiveBasicReturn(final int channelId, final int replyCode,
+                                   final AMQShortString replyText,
+                                   final AMQShortString exchange,
+                                   final AMQShortString routingKey)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new BasicReturnBody(replyCode, replyText, exchange, routingKey));
+        }
+
+    }
+
+    @Override
+    public void receiveBasicDeliver(final int channelId,
+                                    final AMQShortString consumerTag,
+                                    final long deliveryTag,
+                                    final boolean redelivered,
+                                    final AMQShortString exchange,
+                                    final AMQShortString routingKey)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId,
+                                          new BasicDeliverBody(consumerTag,
+                                                               deliveryTag,
+                                                               redelivered,
+                                                               exchange,
+                                                               routingKey));
+        }
+
+    }
+
+    @Override
+    public void receiveBasicGet(final int channelId, final AMQShortString queue, final boolean noAck)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new BasicGetBody(0, queue, noAck));
+        }
+
+    }
+
+    @Override
+    public void receiveBasicGetOk(final int channelId,
+                                  final long deliveryTag,
+                                  final boolean redelivered,
+                                  final AMQShortString exchange,
+                                  final AMQShortString routingKey,
+                                  final long messageCount)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId,
+                                          new BasicGetOkBody(deliveryTag,
+                                                             redelivered,
+                                                             exchange,
+                                                             routingKey,
+                                                             messageCount));
+        }
+
+    }
+
+    @Override
+    public void receiveBasicGetEmpty(final int channelId)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new BasicGetEmptyBody((AMQShortString) null));
+        }
+
+    }
+
+    @Override
+    public void receiveBasicAck(final int channelId, final long deliveryTag, final boolean multiple)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new BasicAckBody(deliveryTag, multiple));
+        }
+
+    }
+
+    @Override
+    public void receiveBasicReject(final int channelId, final long deliveryTag, final boolean requeue)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new BasicRejectBody(deliveryTag, requeue));
+        }
+
+    }
+
+    @Override
+    public void receiveHeartbeat()
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(0, new HeartbeatBody());
+        }
+
+    }
+
+    @Override
+    public ProtocolVersion getProtocolVersion()
+    {
+        return _protocolVersion;
+    }
+
+    public void setProtocolVersion(final ProtocolVersion protocolVersion)
+    {
+        _protocolVersion = protocolVersion;
+    }
+
+    @Override
+    public void receiveMessageContent(final int channelId, final byte[] data)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new ContentBody(data));
+        }
+
+    }
+
+    @Override
+    public void receiveMessageHeader(final int channelId,
+                                     final BasicContentHeaderProperties properties,
+                                     final long bodySize)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQFrame frame = new AMQFrame(channelId, new ContentHeaderBody(properties, bodySize));
+        }
+
+    }
+
+    @Override
+    public void receiveProtocolHeader(final ProtocolInitiation protocolInitiation)
+    {
+        if (LOGGER.isDebugEnabled())
+        {
+            AMQDataBlock frame = protocolInitiation;
+        }
+
+    }
+
+    private void disposeSaslServer()
+    {
+        SaslServer ss = _connection.getSaslServer();
+        if (ss != null)
+        {
+            _connection.setSaslServer(null);
+            try
+            {
+                ss.dispose();
+            }
+            catch (SaslException e)
+            {
+                LOGGER.error("Error disposing of Sasl server: " + e);
+            }
+        }
+    }
+}
diff --git a/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbySystemConfigImpl.java b/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbySystemConfigImpl.java
index 32c5bcd..a8b9eda 100644
--- a/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbySystemConfigImpl.java
+++ b/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbySystemConfigImpl.java
@@ -26,6 +26,7 @@
 import org.apache.qpid.server.logging.LogRecorder;
 import org.apache.qpid.server.model.AbstractSystemConfig;
 import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerShutdownProvider;
 import org.apache.qpid.server.model.ManagedAttributeField;
 import org.apache.qpid.server.model.ManagedObject;
 import org.apache.qpid.server.model.SystemConfigFactoryConstructor;
@@ -47,9 +48,10 @@
     public DerbySystemConfigImpl(final TaskExecutor taskExecutor,
                                  final EventLogger eventLogger,
                                  final LogRecorder logRecorder,
-                                 final BrokerOptions brokerOptions)
+                                 final BrokerOptions brokerOptions,
+                                 final BrokerShutdownProvider brokerShutdownProvider)
     {
-        super(taskExecutor, eventLogger, logRecorder, brokerOptions);
+        super(taskExecutor, eventLogger, logRecorder, brokerOptions, brokerShutdownProvider);
     }
 
     @Override
diff --git a/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCSystemConfigImpl.java b/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCSystemConfigImpl.java
index fd1cad7..a552b17 100644
--- a/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCSystemConfigImpl.java
+++ b/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCSystemConfigImpl.java
@@ -26,6 +26,7 @@
 import org.apache.qpid.server.logging.LogRecorder;
 import org.apache.qpid.server.model.AbstractSystemConfig;
 import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerShutdownProvider;
 import org.apache.qpid.server.model.ManagedAttributeField;
 import org.apache.qpid.server.model.ManagedObject;
 import org.apache.qpid.server.model.SystemConfigFactoryConstructor;
@@ -49,9 +50,10 @@
     public JDBCSystemConfigImpl(final TaskExecutor taskExecutor,
                                 final EventLogger eventLogger,
                                 final LogRecorder logRecorder,
-                                final BrokerOptions brokerOptions)
+                                final BrokerOptions brokerOptions,
+                                final BrokerShutdownProvider brokerShutdownProvider)
     {
-        super(taskExecutor, eventLogger, logRecorder, brokerOptions);
+        super(taskExecutor, eventLogger, logRecorder, brokerOptions, brokerShutdownProvider);
     }
 
     @Override
diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
index e077056..936cc47 100644
--- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
+++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
@@ -122,7 +122,7 @@
         super(attributes, broker);
     }
 
-    @StateTransition(currentState = State.UNINITIALIZED, desiredState = State.ACTIVE)
+    @StateTransition(currentState = {State.UNINITIALIZED,State.ERRORED}, desiredState = State.ACTIVE)
     private void doStart()
     {
         getBroker().getEventLogger().message(ManagementConsoleMessages.STARTUP(OPERATIONAL_LOGGING_NAME));
diff --git a/java/broker-plugins/management-http/src/main/java/resources/addQueue.html b/java/broker-plugins/management-http/src/main/java/resources/addQueue.html
index 352e698..042d6d7 100644
--- a/java/broker-plugins/management-http/src/main/java/resources/addQueue.html
+++ b/java/broker-plugins/management-http/src/main/java/resources/addQueue.html
@@ -39,19 +39,75 @@
             <div class="clear">
                 <div class="formLabel-labelCell">Queue Type:</div>
                 <div class="formLabel-controlCell">
-                    <input type="radio" id="formAddQueueTypeStandard" name="type" value="standard" checked="checked" dojoType="dijit.form.RadioButton" />
-                    <label for="formAddQueueTypeStandard">Standard</label>
-                    &nbsp;
-                    <input type="radio" id="formAddQueueTypePriority" name="type" value="priority" dojoType="dijit.form.RadioButton" />
-                    <label for="formAddQueueTypePriority">Priority</label>
-                    &nbsp;
-                    <input type="radio" id="formAddQueueTypeLVQ" name="type" value="lvq" dojoType="dijit.form.RadioButton" />
-                    <label for="formAddQueueTypeLVQ">LVQ</label>
-                    &nbsp;
-                    <input type="radio" id="formAddQueueTypeSorted" name="type" value="sorted" dojoType="dijit.form.RadioButton" />
-                    <label for="formAddQueueTypeSorted">Sorted</label>
+                    <select id="formAddQueue.type"
+                            dojoType="dijit.form.FilteringSelect"
+                            data-dojo-props="
+                              name: 'type',
+                              value: 'standard',
+                              searchAttr: 'name',
+                              required: true,
+                              promptMessage: 'Type of Queue',
+                              title: 'Enter the queue type'">
+                        <option value="standard">Standard</option>
+                        <option value="priority">Priority</option>
+                        <option value="lvq">LVQ</option>
+                        <option value="sorted">Sorted</option>
+                    </select>
                 </div>
             </div>
+            <div class="clear"></div>
+
+            <div id="formAddQueueType:priority" class="hidden typeSpecificDiv">
+                <div class="clear">
+                    <div class="formLabel-labelCell">Priorities:</div>
+                    <div class="formLabel-controlCell">
+                        <input type="text" id="formAddQueue.priorities"
+                               data-dojo-type="dijit/form/ValidationTextBox"
+                               data-dojo-props="
+                                  name: 'priorities',
+                                  placeHolder: 'number of priorities',
+                                  promptMessage: 'Number of priorities supported by the queue',
+                                  title: 'Enter the number of priorities supported by the queue',
+                                  trim: true"/>
+                    </div>
+                </div>
+                <div class="clear"></div>
+            </div>
+
+            <div id="formAddQueueType:lvq" class="hidden typeSpecificDiv">
+                <div class="clear">
+                    <div class="formLabel-labelCell">LVQ Message Property:</div>
+                    <div class="formLabel-controlCell">
+                        <input type="text" id="formAddQueue.lvqKey"
+                               data-dojo-type="dijit/form/ValidationTextBox"
+                               data-dojo-props="
+                                  name: 'lvqKey',
+                                  placeHolder: 'lvq key',
+                                  promptMessage: 'Name of the message property used to perform the conflation',
+                                  title: 'Enter the name of the message property used to perform the conflation',
+                                  trim: true"/>
+                    </div>
+                </div>
+                <div class="clear"></div>
+            </div>
+
+            <div id="formAddQueueType:sorted" class="hidden typeSpecificDiv">
+                <div class="clear">
+                    <div class="formLabel-labelCell">Sort Message Property*:</div>
+                    <div class="formLabel-controlCell">
+                        <input type="text" id="formAddQueue.sortKey"
+                               data-dojo-type="dijit/form/ValidationTextBox"
+                               data-dojo-props="
+                                  name: 'sortKey',
+                                  placeHolder: 'sort key',
+                                  promptMessage: 'Name of the message property used for sorting the messages on the queue',
+                                  title: 'Enter the name of the message property used for sorting the messages on the queue',
+                                  trim: true"/>
+                    </div>
+                </div>
+                <div class="clear"></div>
+            </div>
+
             <div class="clear">
                 <div class="formLabel-labelCell">Durable?</div>
                 <div class="formLabel-controlCell">
@@ -73,8 +129,8 @@
                               value: '',
                               searchAttr: 'name',
                               required: false,
-                              promptMessage: 'Message durability override. If not default, messages arriving will have durability setting overridden',
-                              title: 'Enter message durability override'">
+                              promptMessage: 'Message persistence override. If not default, messages arriving will have persistence setting overridden',
+                              title: 'Enter message persistence override'">
                         <option value="ALWAYS">Always</option>
                         <option value="DEFAULT">Default</option>
                         <option value="NEVER">Never</option>
@@ -108,66 +164,9 @@
                 </div>
             </div>
 
-            <br/>
-            <div class="clear"></div>
-
-
-            <div id="formAddQueueTypePriority:fields" class="hidden"
-                 data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Priority Queue Settings'">
-                <div class="clear">
-                    <div class="formLabel-labelCell">Priorities:</div>
-                    <div class="formLabel-controlCell">
-                        <input type="text" id="formAddQueue.priorities"
-                               data-dojo-type="dijit/form/ValidationTextBox"
-                               data-dojo-props="
-                                  name: 'priorities',
-                                  placeHolder: 'number of priorities',
-                                  promptMessage: 'Number of priorities supported by the queue',
-                                  title: 'Enter the number of priorities supported by the queue',
-                                  trim: true"/>
-                    </div>
-                </div>
-                <div class="clear"></div>
-            </div>
-
-            <div id="formAddQueueTypeLVQ:fields" class="hidden"
-                 data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Last Value Queue Settings'">
-                <div class="clear">
-                    <div class="formLabel-labelCell">LVQ Message Property:</div>
-                    <div class="formLabel-controlCell">
-                        <input type="text" id="formAddQueue.lvqkey"
-                               data-dojo-type="dijit/form/ValidationTextBox"
-                               data-dojo-props="
-                                  name: 'lvqKey',
-                                  placeHolder: 'lvq key',
-                                  promptMessage: 'Name of the message property used to perform the conflation',
-                                  title: 'Enter the name of the message property used to perform the conflation',
-                                  trim: true"/>
-                    </div>
-                </div>
-                <div class="clear"></div>
-            </div>
-
-            <div id="formAddQueueTypeSorted:fields" class="hidden"
-                 data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Sorted Queue Settings'">
-                <div class="clear">
-                    <div class="formLabel-labelCell">Sort Message Property*:</div>
-                    <div class="formLabel-controlCell">
-                        <input type="text" id="formAddQueue.sortkey"
-                               data-dojo-type="dijit/form/ValidationTextBox"
-                               data-dojo-props="
-                                  name: 'sortKey',
-                                  placeHolder: 'sort key',
-                                  promptMessage: 'Name of the message property used for sorting the messages on the queue',
-                                  title: 'Enter the name of the message property used for sorting the messages on the queue',
-                                  trim: true"/>
-                    </div>
-                </div>
-                <div class="clear"></div>
-            </div>
-
-            <br/>
-            <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Flow Control Settings', open: false">
+            <div class="clear formBox">
+                <fieldset>
+                <legend>Flow Control Settings</legend>
                 <div class="clear">
                     <div class="formLabel-labelCell">Capacity:</div>
                     <div class="formLabel-controlCell">
@@ -194,11 +193,13 @@
                                   trim: true"/>
                     </div>
                 </div>
+                </fieldset>
                 <div class="clear"></div>
             </div>
 
-            <br/>
-            <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Alerting Settings', open: false">
+            <div class="clear formBox">
+                <fieldset>
+                <legend>Alerting Settings</legend>
                 <div class="clear">
                     <div class="formLabel-labelCell">Queue Depth:</div>
                     <div class="formLabel-controlCell">
@@ -264,11 +265,13 @@
                                   trim: true"/>
                     </div>
                 </div>
+                </fieldset>
                 <div class="clear"></div>
             </div>
 
-            <br/>
-            <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Other Settings', open: false">
+            <div class="clear formBox">
+                <fieldset>
+                <legend>Other Settings</legend>
                 <div class="clear">
                     <div class="formLabel-labelCell">Maximum Delivery Retries:</div>
                     <div class="formLabel-controlCell">
@@ -323,9 +326,14 @@
                               title: 'Controls where a shared groups feature is enabled'"/>
                     </div>
                 </div>
+                </fieldset>
                 <div class="clear"></div>
             </div>
 
+          <div class="clear" data-dojo-type="dijit/TitlePane" data-dojo-props="title: 'Context variables',  open: false">
+              <div id="formAddQueue.context" ></div>
+          </div>
+
           <div class="dijitDialogPaneActionBar">
             <!-- submit buttons -->
             <input type="submit" value="Create Queue" label="Create Queue" dojoType="dijit.form.Button" />
diff --git a/java/broker-plugins/management-http/src/main/java/resources/css/common.css b/java/broker-plugins/management-http/src/main/java/resources/css/common.css
index 7c8ca2e..d04117b 100644
--- a/java/broker-plugins/management-http/src/main/java/resources/css/common.css
+++ b/java/broker-plugins/management-http/src/main/java/resources/css/common.css
@@ -262,7 +262,6 @@
 
 /* Required to keep queue type radio buttons on one line when dialog adds scrollbar */
 #addQueue {
-    max-height: 350px;
     overflow: auto;
     width: 630px;
 }
@@ -305,4 +304,4 @@
     width:100%;
     max-height: 140px;
     overflow: auto;
-}
\ No newline at end of file
+}
diff --git a/java/broker-plugins/management-http/src/main/java/resources/editQueue.html b/java/broker-plugins/management-http/src/main/java/resources/editQueue.html
new file mode 100644
index 0000000..aff2b5d
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/editQueue.html
@@ -0,0 +1,300 @@
+<!--
+  ~ 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.
+  -->
+<div class="dijitHidden">
+    <div data-dojo-type="dijit.Dialog" data-dojo-props="title:'Edit Queue'" id="editQueue">
+        <form id="formEditQueue" method="post" dojoType="dijit.form.Form">
+        <div id="formEditQueue.allFields">
+            <div id="formEditQueue.contentPane">
+                <div class="editNoteBanner">NOTE: All changes will only take effect after Virtual Host restart.</div>
+                <div class="clear">
+                    <div class="formLabel-labelCell">Queue Name:</div>
+                    <div class="formLabel-controlCell">
+                        <input type="text" id="formEditQueue.name"
+                               data-dojo-type="dijit/form/ValidationTextBox"
+                               data-dojo-props="
+                                      name: 'name',
+                                      placeHolder: 'queue name',
+                                      required: true,
+                                      promptMessage: 'Name of queue',
+                                      disabled: 'true'"/>
+                    </div>
+                </div>
+
+                <div class="clear">
+                    <div class="formLabel-labelCell">Queue Type:</div>
+                    <div class="formLabel-controlCell">
+                        <input type="text" id="formEditQueue.type"
+                               data-dojo-type="dijit/form/ValidationTextBox"
+                               data-dojo-props="
+                                      name: 'type',
+                                      placeHolder: 'queue type',
+                                      required: true,
+                                      promptMessage: 'Type of queue',
+                                      disabled: 'true'"/>
+                    </div>
+                </div>
+                <div class="clear"></div>
+
+                <div id="formEditQueueType:priority" class="hidden typeSpecificDiv">
+                    <div class="clear">
+                        <div class="formLabel-labelCell">Priorities:</div>
+                        <div class="formLabel-controlCell">
+                            <input type="text" id="formEditQueue.priorities"
+                                   data-dojo-type="dijit/form/ValidationTextBox"
+                                   data-dojo-props="
+                                  name: 'priorities',
+                                  disabled: 'true',
+                                  promptMessage: 'Number of priorities supported by the queue',
+                                  title: 'Enter the number of priorities supported by the queue',
+                                  trim: true"/>
+                        </div>
+                    </div>
+                    <div class="clear"></div>
+                </div>
+
+                <div id="formEditQueueType:lvq" class="hidden typeSpecificDiv">
+                    <div class="clear">
+                        <div class="formLabel-labelCell">LVQ Message Property:</div>
+                        <div class="formLabel-controlCell">
+                            <input type="text" id="formEditQueue.lvqKey"
+                                   data-dojo-type="dijit/form/ValidationTextBox"
+                                   data-dojo-props="
+                                  name: 'lvqKey',
+                                  disabled: 'true',
+                                  promptMessage: 'Name of the message property used to perform the conflation',
+                                  title: 'Enter the name of the message property used to perform the conflation',
+                                  trim: true"/>
+                        </div>
+                    </div>
+                    <div class="clear"></div>
+                </div>
+
+                <div id="formEditQueueType:sorted" class="hidden typeSpecificDiv">
+                    <div class="clear">
+                        <div class="formLabel-labelCell">Sort Message Property*:</div>
+                        <div class="formLabel-controlCell">
+                            <input type="text" id="formEditQueue.sortKey"
+                                   data-dojo-type="dijit/form/ValidationTextBox"
+                                   data-dojo-props="
+                                  name: 'sortKey',
+                                  disabled: 'true',
+                                  promptMessage: 'Name of the message property used for sorting the messages on the queue',
+                                  title: 'Enter the name of the message property used for sorting the messages on the queue',
+                                  trim: true"/>
+                        </div>
+                    </div>
+                    <div class="clear"></div>
+                </div>
+
+                <div class="clear">
+                    <div class="formLabel-labelCell">Durable?</div>
+                    <div class="formLabel-controlCell">
+                        <input type="checkbox" id="formEditQueue.durable"
+                               dojoType="dijit.form.CheckBox"
+                               data-dojo-props="
+                                  name: 'durable',
+                                  value: 'durable',
+                                  disabled: 'true'"/>
+                    </div>
+                </div>
+                <div class="clear">
+                    <div class="formLabel-labelCell">Persist Messages?</div>
+                    <div class="formLabel-controlCell">
+                        <select id="formEditQueue.messageDurability"
+                                dojoType="dijit.form.FilteringSelect"
+                                data-dojo-props="
+                                  name: 'messageDurability',
+                                  value: '',
+                                  searchAttr: 'name',
+                                  required: false,
+                                  promptMessage: 'Message persistence override. If not default, messages arriving will have persistence setting overridden',
+                                  title: 'Enter message persistence override'">
+                            <option value="ALWAYS">Always</option>
+                            <option value="DEFAULT">Default</option>
+                            <option value="NEVER">Never</option>
+                        </select>
+                    </div>
+                </div>
+                <div class="clear">
+                    <div class="formLabel-labelCell">Maximum Ttl:</div>
+                    <div class="formLabel-controlCell">
+                        <input type="text" id="formEditQueue.maximumMessageTtl"
+                               data-dojo-type="dijit/form/ValidationTextBox"
+                               data-dojo-props="
+                                      name: 'maximumMessageTtl',
+                                      placeHolder: 'ttl in ms',
+                                      promptMessage: 'Maximum message time to live (ttl) in ms. Messages arriving with larger ttl values will be overridden by this value',
+                                      title: 'Enter the maximum message time to live in milliseconds',
+                                      trim: true"/>
+                    </div>
+                </div>
+                <div class="clear">
+                    <div class="formLabel-labelCell">Minimum Ttl:</div>
+                    <div class="formLabel-controlCell">
+                        <input type="text" id="formEditQueue.minimumMessageTtl"
+                               data-dojo-type="dijit/form/ValidationTextBox"
+                               data-dojo-props="
+                                      name: 'minimumMessageTtl',
+                                      placeHolder: 'ttl in ms',
+                                      promptMessage: 'Minimum message time to live (ttl) in ms. Messages arriving with smaller ttl values will be overridden by this value',
+                                      title: 'Enter the minimum message time to live in milliseconds',
+                                      trim: true"/>
+                    </div>
+                </div>
+
+                <div class="clear"></div>
+
+                <div class="clear formBox">
+                    <fieldset>
+                    <legend>Flow Control Settings</legend>
+                    <div class="clear">
+                        <div class="formLabel-labelCell">Capacity:</div>
+                        <div class="formLabel-controlCell">
+                            <input type="text" id="formEditQueue.queueFlowControlSizeBytes"
+                                   data-dojo-type="dijit/form/ValidationTextBox"
+                                   data-dojo-props="
+                                      name: 'queueFlowControlSizeBytes',
+                                      placeHolder: 'size in bytes',
+                                      promptMessage: 'Ceiling (in bytes) at which queue will begin to throttle sessions producing messages',
+                                      title: 'Enter the ceiling (in bytes) at which queue will begin to throttle sessions producing messages',
+                                      trim: true"/>
+                        </div>
+                    </div>
+                    <div class="clear">
+                        <div class="formLabel-labelCell">Resume Capacity:</div>
+                        <div class="formLabel-controlCell">
+                            <input type="text" id="formEditQueue.queueFlowResumeSizeBytes"
+                                   data-dojo-type="dijit/form/ValidationTextBox"
+                                   data-dojo-props="
+                                      name: 'queueFlowResumeSizeBytes',
+                                      placeHolder: 'size in bytes',
+                                      promptMessage: 'Floor (in bytes) at which queue will cease to throttle sessions producing messages',
+                                      title: 'Enter the floor (in bytes) at which queue will cease to throttle sessions producing messages',
+                                      trim: true"/>
+                        </div>
+                    </div>
+                    </fieldset>
+                    <div class="clear"></div>
+                </div>
+
+                <div class="clear formBox">
+                    <fieldset>
+                        <legend>Alerting Settings</legend>
+                        <div class="clear">
+                        <div class="formLabel-labelCell">Queue Depth:</div>
+                        <div class="formLabel-controlCell">
+                            <input type="text" id="formEditQueue.alertThresholdQueueDepthMessages"
+                                   data-dojo-type="dijit/form/ValidationTextBox"
+                                   data-dojo-props="
+                                      name: 'alertThresholdQueueDepthMessages',
+                                      placeHolder: 'number of messages',
+                                      promptMessage: 'Ceiling value for number of messages on queue before alerts will be generated',
+                                      title: 'Enter the ceiling value for number of messages on queue before alerts will be generated',
+                                      trim: true"/>
+                        </div>
+                    </div>
+                    <div class="clear">
+                        <div class="formLabel-labelCell">Queue Depth:</div>
+                        <div class="formLabel-controlCell">
+                            <input type="text" id="formEditQueue.alertThresholdQueueDepthBytes"
+                                   data-dojo-type="dijit/form/ValidationTextBox"
+                                   data-dojo-props="
+                                      name: 'alertThresholdQueueDepthBytes',
+                                      placeHolder: 'total message size in bytes',
+                                      promptMessage: 'Ceiling value (in bytes) for total size of all messages on the queue before alerts will be generated',
+                                      title: 'Enter the ceiling value (in bytes) for total size of all messages on the queue before alerts will be generated',
+                                      trim: true"/>
+                        </div>
+                    </div>
+                    <div class="clear">
+                        <div class="formLabel-labelCell">Message Age:</div>
+                        <div class="formLabel-controlCell">
+                            <input type="text" id="formEditQueue.alertThresholdMessageAge"
+                                   data-dojo-type="dijit/form/ValidationTextBox"
+                                   data-dojo-props="
+                                      name: 'alertThresholdMessageAge',
+                                      placeHolder: 'time in ms',
+                                      promptMessage: 'Message age (in milliseconds) above which alerts will be generated',
+                                      title: 'Enter the message age (in milliseconds) above which alerts will be generated',
+                                      trim: true"/>
+                        </div>
+                    </div>
+                    <div class="clear">
+                        <div class="formLabel-labelCell">Message Size:</div>
+                        <div class="formLabel-controlCell">
+                            <input type="text" id="formEditQueue.alertThresholdMessageSize"
+                                   data-dojo-type="dijit/form/ValidationTextBox"
+                                   data-dojo-props="
+                                      name: 'alertThresholdMessageSize',
+                                      placeHolder: 'message size in bytes',
+                                      promptMessage: 'Message size (in bytes) above which alerts will be generated',
+                                      title: 'Enter the message size (in bytes) above which alerts will be generated',
+                                      trim: true"/>
+                        </div>
+                    </div>
+                    <div class="clear">
+                        <div class="formLabel-labelCell">Gap between alerts:</div>
+                        <div class="formLabel-controlCell">
+                            <input type="text" id="formEditQueue.alertRepeatGap"
+                                   data-dojo-type="dijit/form/ValidationTextBox"
+                                   data-dojo-props="
+                                      name: 'alertRepeatGap',
+                                      placeHolder: 'time in ms',
+                                      promptMessage: 'Minimum time (in milliseconds) between each alert',
+                                      title: 'Enter the minimum time (in milliseconds) between each alert.',
+                                      trim: true"/>
+                        </div>
+                    </div>
+                    </fieldset>
+                    <div class="clear"></div>
+                </div>
+
+                <div class="clear formBox">
+                    <fieldset>
+                    <legend>Other Settings</legend>
+                    <div class="clear">
+                        <div class="formLabel-labelCell">Maximum Delivery Retries:</div>
+                        <div class="formLabel-controlCell">
+                            <input type="text" id="formEditQueue.maximumDeliveryAttempts"
+                                   data-dojo-type="dijit/form/ValidationTextBox"
+                                   data-dojo-props="
+                                      name: 'maximumDeliveryAttempts',
+                                      placeHolder: 'number of retries',
+                                      promptMessage: 'Maximum number of delivery attempts before the message will be sent to the alternate exchange',
+                                      title: 'Enter the maximum number of delivery attempts before the message will be sent to the alternate exchange',
+                                      trim: true"/>
+                        </div>
+                    </div>
+                    </fieldset>
+                    <div class="clear"></div>
+                </div>
+
+                <div data-dojo-type="dijit/TitlePane" data-dojo-props="title: 'Context variables',  open: false">
+                    <div id="formEditQueue.context" ></div>
+                </div>
+            </div>
+            <div class="dijitDialogPaneActionBar">
+                <button data-dojo-type="dijit/form/Button" id="formEditQueue.saveButton" data-dojo-props="label: 'Save'">Save</button>
+                <button data-dojo-type="dijit/form/Button" id="formEditQueue.cancelButton" data-dojo-props="label: 'Cancel'" ></button>
+            </div>
+        </div>
+
+        </form>
+    </div>
+</div>
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/ContextVariablesEditor.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/ContextVariablesEditor.js
index e5d341d..a3e4023 100644
--- a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/ContextVariablesEditor.js
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/ContextVariablesEditor.js
@@ -77,8 +77,8 @@
         var addButton = registry.byNode(addButtonNode);
         var deleteButton = registry.byNode(deleteButtonNode);
         var layout = [[
-                      { name: "Name", field: "name", width: "40%", editable: true, selectOnClick: false, type: dojox.grid.cells._Widget, widgetClass: dijit.form.TextBox },
-                      { name: 'Actual Value', field: 'actualValue', width: '30%', editable: true, selectOnClick: false, type: dojox.grid.cells._Widget, widgetClass: dijit.form.TextBox},
+                      { name: "Name", field: "name", width: "40%", editable: true},
+                      { name: 'Actual Value', field: 'actualValue', width: '30%', editable: true},
                       { name: 'Effective Value', field: 'effectiveValue', width: '30%', editable: false}
                     ]];
         var data = [];
@@ -177,6 +177,38 @@
         }
         this.setData(actualValues, allEffectiveValues, inheritedActualValues);
     },
+    loadInheritedData: function(restUrl)
+    {
+        var allEffectiveValues = null;
+        xhr.get(
+            {
+              url: restUrl,
+              sync: true,
+              content: { actuals: false },
+              handleAs: "json",
+              load: function(data)
+              {
+                allEffectiveValues = data[0].context;
+              }
+            }
+        );
+
+        var inheritedActualValues = null;
+        xhr.get(
+            {
+              url: restUrl,
+              sync: true,
+              content: { actuals: true, inheritedActuals: true},
+              handleAs: "json",
+              load: function(data)
+              {
+                inheritedActualValues = data[0].context;
+              }
+            }
+        );
+
+        this.setData({}, allEffectiveValues, inheritedActualValues);
+    },
     setData: function(actualValues, allEffectiveValues, inheritedActualValues)
     {
       this.value = actualValues;
@@ -523,4 +555,4 @@
     }
 
   });
-});
\ No newline at end of file
+});
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js
index b4ef7b4..5b441a7 100644
--- a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js
@@ -34,6 +34,7 @@
         "qpid/management/moveCopyMessages",
         "qpid/management/showMessage",
         "qpid/management/UserPreferences",
+        "qpid/management/editQueue",
         "dojo/store/JsonRest",
         "dojox/grid/EnhancedGrid",
         "dojo/data/ObjectStore",
@@ -42,7 +43,7 @@
         "dojox/grid/enhanced/plugins/IndirectSelection",
         "dojo/domReady!"],
        function (xhr, parser, query, registry, connect, event, json, properties, updater, util, formatter,
-                 UpdatableStore, addBinding, moveMessages, showMessage, UserPreferences, JsonRest, EnhancedGrid, ObjectStore, entities) {
+                 UpdatableStore, addBinding, moveMessages, showMessage, UserPreferences, editQueue, JsonRest, EnhancedGrid, ObjectStore, entities) {
 
            function Queue(name, parent, controller) {
                this.name = name;
@@ -172,6 +173,12 @@
                                         event.stop(evt);
                                         that.deleteQueue();
                                     });
+                            var editQueueButton = query(".editQueueButton", contentPane.containerNode)[0];
+                            connect.connect(registry.byNode(editQueueButton), "onClick",
+                                    function(evt){
+                                        event.stop(evt);
+                                        editQueue.show({nodeName:that.modelObj.parent.parent.name, hostName:that.modelObj.parent.name,queueName:that.name});
+                                    });
                             UserPreferences.addListener(that);
                         }});
 
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addQueue.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addQueue.js
index 444ed67..236efb2 100644
--- a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addQueue.js
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addQueue.js
@@ -27,7 +27,9 @@
         "dojo/_base/array",
         "dojo/_base/event",
         'dojo/_base/json',
+        "dojo/query",
         'qpid/common/util',
+        "qpid/common/ContextVariablesEditor",
         "dijit/form/NumberSpinner", // required by the form
         /* dojox/ validate resources */
         "dojox/validate/us", "dojox/validate/web",
@@ -42,22 +44,14 @@
         /* basic dojox classes */
         "dojox/form/BusyButton", "dojox/form/CheckedMultiSelect",
         "dojo/domReady!"],
-    function (xhr, dom, construct, win, registry, parser, array, event, json, util) {
+    function (xhr, dom, construct, win, registry, parser, array, event, json, query, util) {
 
         var addQueue = {};
 
         var node = construct.create("div", null, win.body(), "last");
 
-        var typeSpecificFields = {
-                        priorities: "priority",
-                        lvqKey: "lvq",
-                        sortKey: "sorted"
-                    };
-
-        var requiredFields = {
-                priority: "priorities",
-                sorted: "sortkey"
-            };
+        var typeSpecificFields = { priorities: "priority", lvqKey: "lvq", sortKey: "sorted" };
+        var requiredFields = { sorted: "sortKey"};
 
         var fieldConverters = {
                 queueFlowControlSizeBytes:        parseInt,
@@ -96,8 +90,8 @@
                                 newQueue["messageGroupSharedGroups"] = true;
                             }
                         }
-                        else if (!typeSpecificFields.hasOwnProperty(propName) ||
-                                        formValues[ "type" ] === typeSpecificFields[ propName ]) {
+                        else if (!typeSpecificFields.hasOwnProperty(propName) || formValues[ "type" ] === typeSpecificFields[ propName ])
+                        {
                             if(formValues[ propName ] !== "") {
                                 if (fieldConverters.hasOwnProperty(propName))
                                 {
@@ -125,36 +119,29 @@
                             addQueue.dialogNode = dom.byId("addQueue");
                             parser.instantiate([addQueue.dialogNode]);
 
-                            // for children which have name type, add a function to make all the associated rows
-                            // visible / invisible as the radio button is checked / unchecked
-
+                            // for children which have name type, add a function to make all the associated atrributes
+                            // visible / invisible as the select is changed
                             theForm = registry.byId("formAddQueue");
-                            array.forEach(theForm.getDescendants(), function(widget)
+                            var typeSelector = registry.byId("formAddQueue.type");
+                            typeSelector.on("change", function(value)
+                            {
+                                query(".typeSpecificDiv").forEach(function(node, index, arr)
                                 {
-                                    if(widget.name === "type") {
-                                        widget.on("change", function(isChecked) {
-
-                                            var objId = widget.id + ":fields";
-                                            var obj = registry.byId(objId);
-                                            if(obj) {
-                                                if(isChecked) {
-                                                    obj.domNode.style.display = "block";
-                                                } else {
-                                                    obj.domNode.style.display = "none";
-                                                }
-                                                obj.resize();
-                                                var widgetValue = widget.value;
-                                                if (requiredFields.hasOwnProperty(widgetValue))
-                                                {
-                                                    dijit.byId('formAddQueue.' + requiredFields[widgetValue]).required = isChecked;
-                                                }
-
-                                                util.applyMetadataToWidgets(obj.domNode, "Queue", widgetValue);
-                                            }
-                                        })
+                                    if (node.id === "formAddQueueType:" + value)
+                                    {
+                                        node.style.display = "block";
+                                        util.applyMetadataToWidgets(node, "Queue", value);
                                     }
-
+                                    else
+                                    {
+                                        node.style.display = "none";
+                                    }
                                 });
+                                for(var requiredField in requiredFields)
+                                {
+                                    dijit.byId('formAddQueue.' + requiredFields[requiredField]).required = (requiredField == value);
+                                }
+                            });
 
                             theForm.on("submit", function(e) {
 
@@ -200,6 +187,14 @@
                             registry.byId("addQueue").show();
                             util.applyMetadataToWidgets(form.domNode, "Queue", "standard");
 
+                            if (!this.context)
+                            {
+                             this.context = new qpid.common.ContextVariablesEditor({name: 'context', title: 'Context variables'});
+                             this.context.placeAt(dom.byId("formAddQueue.context"));
+                            }
+
+                            var escapedUrl = "api/latest/virtualhost/" + encodeURIComponent(addQueue.vhostnode) + "/" + encodeURIComponent(addQueue.vhost);
+                            this.context.loadInheritedData(escapedUrl);
         };
 
         return addQueue;
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addVirtualHostNodeAndVirtualHost.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addVirtualHostNodeAndVirtualHost.js
index 226674b..0a18a89 100644
--- a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addVirtualHostNodeAndVirtualHost.js
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addVirtualHostNodeAndVirtualHost.js
@@ -134,35 +134,10 @@
                 this.virtualHostContext.placeAt(dom.byId("addVirtualHost.context"));
 
         }
-        var inheritedActualValues = null;
-        xhr.get(
-            {
-              url: "api/latest/broker",
-              sync: true,
-              content: { actuals: true, inheritedActuals: true},
-              handleAs: "json",
-              load: function(data)
-              {
-                inheritedActualValues = data[0].context;
-              }
-            }
-        );
 
-        var effectiveValues = null;
-        xhr.get(
-            {
-              url: "api/latest/broker",
-              sync: true,
-              handleAs: "json",
-              load: function(data)
-              {
-                effectiveValues = data[0].context;
-              }
-            }
-        );
+        this.virtualHostNodeContext.loadInheritedData("api/latest/broker");
+        this.virtualHostContext.setData({}, this.virtualHostNodeContext.effectiveValues,this.virtualHostNodeContext.inheritedActualValues);
 
-        this.virtualHostNodeContext.setData({},effectiveValues,inheritedActualValues);
-        this.virtualHostContext.setData({},effectiveValues,inheritedActualValues);
         this.dialog.show();
         if (!this.resizeEventRegistered)
         {
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/editQueue.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/editQueue.js
new file mode 100644
index 0000000..06c9672
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/editQueue.js
@@ -0,0 +1,232 @@
+/*
+ *
+ * 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.
+ *
+ */
+define(["dojo/_base/xhr",
+        "dojox/html/entities",
+        "dojo/_base/array",
+        "dojo/_base/event",
+        "dojo/_base/lang",
+        "dojo/_base/window",
+        "dojo/dom",
+        "dojo/dom-construct",
+        "dijit/registry",
+        "dojo/parser",
+        'dojo/json',
+        "dojo/query",
+        "qpid/common/util",
+        "dojo/text!editQueue.html",
+        "qpid/common/ContextVariablesEditor",
+        "dijit/Dialog",
+        "dijit/form/CheckBox",
+        "dijit/form/FilteringSelect",
+        "dijit/form/ValidationTextBox",
+        "dijit/form/Button",
+        "dijit/form/Form",
+        "dojox/validate/us",
+        "dojox/validate/web",
+        "dojo/domReady!"],
+  function (xhr, entities, array, event, lang, win, dom, domConstruct, registry, parser, json, query, util, template)
+  {
+    var fields = ["name",
+                  "type",
+                  "durable",
+                  "messageDurability",
+                  "maximumMessageTtl",
+                  "minimumMessageTtl",
+                  "queueFlowControlSizeBytes",
+                  "queueFlowResumeSizeBytes",
+                  "alertThresholdQueueDepthMessages",
+                  "alertThresholdQueueDepthBytes",
+                  "alertThresholdMessageAge",
+                  "alertThresholdMessageSize",
+                  "alertRepeatGap",
+                  "maximumDeliveryAttempts",
+                  "priorities",
+                  "lvqKey",
+                  "sortKey"];
+
+    var numericFieldNames = ["maximumMessageTtl",
+                  "minimumMessageTtl",
+                  "queueFlowControlSizeBytes",
+                  "queueFlowResumeSizeBytes",
+                  "alertThresholdQueueDepthMessages",
+                  "alertThresholdQueueDepthBytes",
+                  "alertThresholdMessageAge",
+                  "alertThresholdMessageSize",
+                  "alertRepeatGap",
+                  "maximumDeliveryAttempts"];
+
+    var queueEditor =
+    {
+      init: function()
+      {
+        var that=this;
+        this.containerNode = domConstruct.create("div", {innerHTML: template});
+        parser.parse(this.containerNode);
+        this.allFieldsContainer = dom.byId("formEditQueue.allFields");
+        this.dialog = registry.byId("editQueue");
+        this.saveButton = registry.byId("formEditQueue.saveButton");
+        this.cancelButton = registry.byId("formEditQueue.cancelButton");
+        this.cancelButton.on("click", function(e){that._cancel(e);});
+        this.saveButton.on("click", function(e){that._save(e);});
+        for(var i = 0; i < fields.length; i++)
+        {
+            var fieldName = fields[i];
+            this[fieldName] = registry.byId("formEditQueue." + fieldName);
+        }
+        this.form = registry.byId("formEditQueue");
+        this.form.on("submit", function(){return false;});
+        this.typeSelector = registry.byId("formEditQueue.type");
+      },
+      show: function(hostData)
+      {
+        var that=this;
+        if (!this.context)
+        {
+         this.context = new qpid.common.ContextVariablesEditor({name: 'context', title: 'Context variables'});
+         this.context.placeAt(dom.byId("formEditQueue.context"));
+        }
+        this.query = "api/latest/queue/" + encodeURIComponent(hostData.nodeName) + "/" + encodeURIComponent(hostData.hostName) + "/" + encodeURIComponent(hostData.queueName);
+        this.dialog.set("title", "Edit Queue - " + entities.encode(String(hostData.queueName)));
+        xhr.get(
+            {
+              url: this.query,
+              sync: true,
+              content: { actuals: true },
+              handleAs: "json",
+              load: function(data)
+              {
+                that._show(data[0], hostData);
+              }
+            }
+        );
+        var queueType = this.typeSelector.get("value");
+        query(".typeSpecificDiv").forEach(function(node, index, arr){
+            if (node.id === "formEditQueueType:" + queueType)
+            {
+                node.style.display = "block";
+                util.applyMetadataToWidgets(node, "Queue", queueType);
+            }
+            else
+            {
+                node.style.display = "none";
+            }
+        });
+      },
+      destroy: function()
+      {
+        if (this.dialog)
+        {
+            this.dialog.destroyRecursive();
+            this.dialog = null;
+        }
+
+        if (this.containerNode)
+        {
+            domConstruct.destroy(this.containerNode);
+            this.containerNode = null;
+        }
+      },
+      _cancel: function(e)
+      {
+          this.dialog.hide();
+      },
+      _save: function(e)
+      {
+          event.stop(e);
+          if(this.form.validate())
+          {
+              var data = util.getFormWidgetValues(this.form, this.initialData);
+              var context = this.context.get("value");
+              if (context && !util.equals(context, this.initialData.context))
+              {
+                data["context"] = context;
+              }
+              var success = false,failureReason=null;
+              xhr.put({
+                  url: this.query,
+                  sync: true,
+                  handleAs: "json",
+                  headers: { "Content-Type": "application/json"},
+                  putData: json.stringify(data),
+                  load: function(x) {success = true; },
+                  error: function(error) {success = false; failureReason = error;}
+              });
+
+              if(success === true)
+              {
+                  this.dialog.hide();
+              }
+              else
+              {
+                  util.xhrErrorHandler(failureReason);
+              }
+          }
+          else
+          {
+              alert('Form contains invalid data.  Please correct first');
+          }
+      },
+      _show:function(actualData, effectiveData)
+      {
+
+          this.initialData = actualData;
+          for(var i = 0; i < fields.length; i++)
+          {
+            var fieldName = fields[i];
+            var widget = this[fieldName];
+            widget.reset();
+
+            if (widget instanceof dijit.form.CheckBox)
+            {
+              widget.set("checked", actualData[fieldName]);
+            }
+            else
+            {
+              widget.set("value", actualData[fieldName]);
+            }
+          }
+
+          var that = this;
+          util.applyMetadataToWidgets(that.allFieldsContainer, "Queue", actualData.type);
+
+          this.context.load(this.query, {actualValues:actualData.context, effectiveValues:effectiveData.context});
+
+          // Add regexp to the numeric fields
+          for(var i = 0; i < numericFieldNames.length; i++)
+          {
+            this[numericFieldNames[i]].set("regExpGen", util.numericOrContextVarRegexp);
+          }
+
+          this.dialog.startup();
+          this.dialog.show();
+          if (!this.resizeEventRegistered)
+          {
+            this.resizeEventRegistered = true;
+            util.resizeContentAreaAndRepositionDialog(dom.byId("formEditQueue.contentPane"), this.dialog);
+          }
+      }
+    };
+
+    queueEditor.init();
+
+    return queueEditor;
+  }
+);
diff --git a/java/broker-plugins/management-http/src/main/java/resources/showQueue.html b/java/broker-plugins/management-http/src/main/java/resources/showQueue.html
index e5b9699..a068868 100644
--- a/java/broker-plugins/management-http/src/main/java/resources/showQueue.html
+++ b/java/broker-plugins/management-http/src/main/java/resources/showQueue.html
@@ -198,7 +198,7 @@
             </div>
         </div>
         <div class="clear">
-            <div class="formLabel-labelCell">Alert frequency:</div>
+            <div class="formLabel-labelCell">Gap between alerts:</div>
             <div>
                 <span class="alertRepeatGap"></span>
                 <span class="alertRepeatGapUnits"></span>
@@ -208,6 +208,7 @@
     </div>
 
     <div class="dijitDialogPaneActionBar">
+        <button data-dojo-type="dijit.form.Button" class="editQueueButton" type="button">Edit Queue</button>
         <button data-dojo-type="dijit.form.Button" class="deleteQueueButton" type="button">Delete Queue</button>
     </div>
 </div>
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagementPluginImpl.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagementPluginImpl.java
index a38aa9e..6c962c2 100644
--- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagementPluginImpl.java
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagementPluginImpl.java
@@ -29,6 +29,7 @@
 import java.util.Map;
 import java.util.Set;
 
+import javax.management.InstanceAlreadyExistsException;
 import javax.management.JMException;
 
 import org.apache.log4j.Logger;
@@ -103,7 +104,7 @@
         return _usePlatformMBeanServer;
     }
 
-    @StateTransition(currentState = State.UNINITIALIZED, desiredState = State.ACTIVE)
+    @StateTransition(currentState = {State.UNINITIALIZED,State.ERRORED}, desiredState = State.ACTIVE)
     private void doStart() throws JMException, IOException
     {
         _allowPortActivation = true;
@@ -340,8 +341,8 @@
                         mbean = new UserManagementMBean((PasswordCredentialManagingAuthenticationProvider<?>) object, _objectRegistry);
                         registerMBean(object, _pluginMBeanProvider, mbean);
                     }
-                    createAdditionalMBeansFromProvidersIfNecessary(object, _objectRegistry);
                 }
+                createAdditionalMBeansFromProvidersIfNecessary(object, _objectRegistry);
             }
         }
         return mbean;
@@ -351,10 +352,27 @@
     {
         if (!providerMBeanExists(host, _pluginMBeanProvider))
         {
-            VirtualHostMBean mbean = new VirtualHostMBean(host, _objectRegistry);
-            registerMBean(host, _pluginMBeanProvider, mbean);
             host.addChangeListener(_changeListener);
-            return mbean;
+            try
+            {
+                VirtualHostMBean mbean = new VirtualHostMBean(host, _objectRegistry);
+                registerMBean(host, _pluginMBeanProvider, mbean);
+                return mbean;
+            }
+            catch (InstanceAlreadyExistsException e)
+            {
+                VirtualHostNode parent = host.getParent(VirtualHostNode.class);
+                Set<ConfiguredObject<?>> registered = _children.keySet();
+                for (ConfiguredObject<?> object: registered)
+                {
+                    if (object instanceof VirtualHost && object.getParent(VirtualHostNode.class) == parent)
+                    {
+                        LOGGER.warn("Unexpected MBean is found for VirtualHost " + object + " belonging to node " +  parent);
+                    }
+                }
+
+                throw e;
+            }
         }
         return null;
     }
@@ -392,24 +410,21 @@
                 }
                 unregisterObjectMBeans(object);
                 _children.remove(object);
-                destroyChildrenMBeansIfVirtualHostNode(object);
+                destroyChildrenMBeans(object);
             }
         }
     }
 
-    private void destroyChildrenMBeansIfVirtualHostNode(ConfiguredObject<?> child)
+    private void destroyChildrenMBeans(ConfiguredObject<?> object)
     {
-        if (child instanceof VirtualHostNode)
+        for (Iterator<ConfiguredObject<?>> iterator = _children.keySet().iterator(); iterator.hasNext();)
         {
-            for (Iterator<ConfiguredObject<?>> iterator = _children.keySet().iterator(); iterator.hasNext();)
+            ConfiguredObject<?> registeredObject = iterator.next();
+            ConfiguredObject<?> parent = registeredObject.getParent(object.getCategoryClass());
+            if (parent == object)
             {
-                ConfiguredObject<?> registeredObject = iterator.next();
-                ConfiguredObject<?> parent = registeredObject.getParent(VirtualHostNode.class);
-                if (parent == child)
-                {
-                    registeredObject.removeChangeListener(_changeListener);
-                    unregisterObjectMBeans(registeredObject);
-                }
+                registeredObject.removeChangeListener(_changeListener);
+                unregisterObjectMBeans(registeredObject);
                 iterator.remove();
             }
         }
diff --git a/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemorySystemConfigImpl.java b/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemorySystemConfigImpl.java
index f644b8f..3f52152 100644
--- a/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemorySystemConfigImpl.java
+++ b/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemorySystemConfigImpl.java
@@ -26,6 +26,7 @@
 import org.apache.qpid.server.logging.LogRecorder;
 import org.apache.qpid.server.model.AbstractSystemConfig;
 import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerShutdownProvider;
 import org.apache.qpid.server.model.ManagedObject;
 import org.apache.qpid.server.model.SystemConfigFactoryConstructor;
 
@@ -39,9 +40,10 @@
     public MemorySystemConfigImpl(final TaskExecutor taskExecutor,
                                   final EventLogger eventLogger,
                                   final LogRecorder logRecorder,
-                                  final BrokerOptions brokerOptions)
+                                  final BrokerOptions brokerOptions,
+                                  final BrokerShutdownProvider brokerShutdownProvider)
     {
-        super(taskExecutor, eventLogger, logRecorder, brokerOptions);
+        super(taskExecutor, eventLogger, logRecorder, brokerOptions, brokerShutdownProvider);
     }
 
     @Override
diff --git a/java/perftests/etc/chartdefs/1001-MessageSize-Transient-ByteSec.chartdef b/java/perftests/etc/chartdefs/1001-MessageSize-Transient-ByteSec.chartdef
index 73d1a93..2327fb6 100644
--- a/java/perftests/etc/chartdefs/1001-MessageSize-Transient-ByteSec.chartdef
+++ b/java/perftests/etc/chartdefs/1001-MessageSize-Transient-ByteSec.chartdef
@@ -20,7 +20,7 @@
 chartType=XYLINE
 chartTitle=Impact of Message Size Bytes/S
 chartSubtitle=Transient messages
-chartDescription=1P 1C, transient, auto-ack, with message payload between 256-262144 bytes ${baselineName}.
+chartDescription=1P 1C, transient, auto-ack, with message payload between 256-262144 bytes ${baselineName}, single queue.
 
 xAxisTitle=Message Size (B)
 yAxisTitle=Throughput (KB/s)
diff --git a/java/perftests/etc/chartdefs/1002-MessageSize-Persistent-ByteSec.chartdef b/java/perftests/etc/chartdefs/1002-MessageSize-Persistent-ByteSec.chartdef
index 2cd5e8d..cd70299 100644
--- a/java/perftests/etc/chartdefs/1002-MessageSize-Persistent-ByteSec.chartdef
+++ b/java/perftests/etc/chartdefs/1002-MessageSize-Persistent-ByteSec.chartdef
@@ -20,7 +20,7 @@
 chartType=XYLINE
 chartTitle=Impact of Message Size Bytes/S
 chartSubtitle=Persistent messages
-chartDescription=1P 1C, persistent, auto-ack, with message payload between 256-262144 bytes.
+chartDescription=1P 1C, persistent, auto-ack, with message payload between 256-262144 bytes, single queue.
 
 xAxisTitle=Message Size (B)
 yAxisTitle=Throughput (KB/s)
diff --git a/java/perftests/etc/chartdefs/1003-MessageSize-Transient-MsgSec.chartdef b/java/perftests/etc/chartdefs/1003-MessageSize-Transient-MsgSec.chartdef
index ae59f61..979136e 100644
--- a/java/perftests/etc/chartdefs/1003-MessageSize-Transient-MsgSec.chartdef
+++ b/java/perftests/etc/chartdefs/1003-MessageSize-Transient-MsgSec.chartdef
@@ -20,7 +20,7 @@
 chartType=XYLINE
 chartTitle=Impact of Message Size
 chartSubtitle=Transient messages
-chartDescription=1P 1C, transient, auto-ack, with message payload between 256-262144 bytes.
+chartDescription=1P 1C, transient, auto-ack, with message payload between 256-262144 bytes, single queue.
 
 xAxisTitle=Message Size (B)
 yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1004-MessageSize-Persistent-MsgSec.chartdef b/java/perftests/etc/chartdefs/1004-MessageSize-Persistent-MsgSec.chartdef
index f5ce766..fef5509 100644
--- a/java/perftests/etc/chartdefs/1004-MessageSize-Persistent-MsgSec.chartdef
+++ b/java/perftests/etc/chartdefs/1004-MessageSize-Persistent-MsgSec.chartdef
@@ -20,7 +20,7 @@
 chartType=XYLINE
 chartTitle=Impact of Message Size
 chartSubtitle=Persistent messages
-chartDescription=1P 1C, persistent, auto-ack, with message payload between 256-262144 bytes.
+chartDescription=1P 1C, persistent, auto-ack, with message payload between 256-262144 bytes, single queue.
 
 xAxisTitle=Message Size (B)
 yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1011-VaryingNumberOfProducers-AutoAck.chartdef b/java/perftests/etc/chartdefs/1011-VaryingNumberOfProducers-AutoAck.chartdef
index d67c888..8ad987e 100644
--- a/java/perftests/etc/chartdefs/1011-VaryingNumberOfProducers-AutoAck.chartdef
+++ b/java/perftests/etc/chartdefs/1011-VaryingNumberOfProducers-AutoAck.chartdef
@@ -20,7 +20,7 @@
 chartType=XYLINE
 chartTitle=Varying number of producers - auto ack
 chartSubtitle=Persistent 1KB messages
-chartDescription=1,2,5,10 P/Cs, persistent, auto-ack, with message payload 1KB.
+chartDescription=1,2,5,10 P/Cs, persistent, auto-ack, with message payload 1KB, single queue.
 
 xAxisTitle=Producers
 yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1012-VaryingNumberOfConsumers-AutoAck.chartdef b/java/perftests/etc/chartdefs/1012-VaryingNumberOfConsumers-AutoAck.chartdef
index b78c7c5..599c37c 100644
--- a/java/perftests/etc/chartdefs/1012-VaryingNumberOfConsumers-AutoAck.chartdef
+++ b/java/perftests/etc/chartdefs/1012-VaryingNumberOfConsumers-AutoAck.chartdef
@@ -20,7 +20,7 @@
 chartType=XYLINE
 chartTitle=Varying number of consumers - auto ack
 chartSubtitle=Persistent 1KB messages
-chartDescription=1,2,5,10 P/Cs, persistent, auto-ack, with message payload 1KB.
+chartDescription=1,2,5,10 P/Cs, persistent, auto-ack, with message payload 1KB, single queue.
 
 xAxisTitle=Consumers
 yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1015-VaryingNumberOfProducers-SessionTrans.chartdef b/java/perftests/etc/chartdefs/1015-VaryingNumberOfProducers-SessionTrans.chartdef
index d00d1e9..d22594c 100644
--- a/java/perftests/etc/chartdefs/1015-VaryingNumberOfProducers-SessionTrans.chartdef
+++ b/java/perftests/etc/chartdefs/1015-VaryingNumberOfProducers-SessionTrans.chartdef
@@ -20,7 +20,7 @@
 chartType=XYLINE
 chartTitle=Varying number of producers - transacted
 chartSubtitle=Persistent 1KB messages
-chartDescription=1,2,5,10 P/Cs, persistent, transacted, with message payload 1KB.
+chartDescription=1,2,5,10 P/Cs, persistent, transacted, with message payload 1KB, single queue.
 
 xAxisTitle=Producers
 yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1016-VaryingNumberOfConsumers-SessionTrans.chartdef b/java/perftests/etc/chartdefs/1016-VaryingNumberOfConsumers-SessionTrans.chartdef
index a808334..0e78117 100644
--- a/java/perftests/etc/chartdefs/1016-VaryingNumberOfConsumers-SessionTrans.chartdef
+++ b/java/perftests/etc/chartdefs/1016-VaryingNumberOfConsumers-SessionTrans.chartdef
@@ -20,7 +20,7 @@
 chartType=XYLINE
 chartTitle=Varying number of consumers - transacted
 chartSubtitle=Persistent 1KB messages
-chartDescription=1,2,5,10 P/Cs, persistent, transacted, with message payload 1KB.
+chartDescription=1,2,5,10 P/Cs, persistent, transacted, with message payload 1KB, single queue.
 
 xAxisTitle=Consumers
 yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1021-AcknowledgementModes-Persistent.chartdef b/java/perftests/etc/chartdefs/1021-AcknowledgementModes-Persistent.chartdef
index a8abd6f..7d1abe6 100644
--- a/java/perftests/etc/chartdefs/1021-AcknowledgementModes-Persistent.chartdef
+++ b/java/perftests/etc/chartdefs/1021-AcknowledgementModes-Persistent.chartdef
@@ -20,7 +20,7 @@
 chartType=BAR
 chartTitle=Performance of acknowledgement modes
 chartSubtitle=Persistent messages (1KB)
-chartDescription=1P 1C, persistent, with message payload 1KB.
+chartDescription=1P 1C, persistent, with message payload 1KB, single queue.
 
 xAxisTitle=Acknowledge mode (0=session transacted; 1=auto-acknowledge)
 yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1022-AcknowledgementModes-Transient.chartdef b/java/perftests/etc/chartdefs/1022-AcknowledgementModes-Transient.chartdef
index ebc040c..662cb85 100644
--- a/java/perftests/etc/chartdefs/1022-AcknowledgementModes-Transient.chartdef
+++ b/java/perftests/etc/chartdefs/1022-AcknowledgementModes-Transient.chartdef
@@ -20,7 +20,7 @@
 chartType=BAR
 chartTitle=Performance of acknowledgement modes
 chartSubtitle=Transient messages (1024b)
-chartDescription=1P 1C, transient, with message payload 1KB.
+chartDescription=1P 1C, transient, with message payload 1KB, single queue.
 
 xAxisTitle=Acknowledge mode (0=session transacted; 1=auto-acknowledge)
 yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1030-BatchSize-Equal.chartdef b/java/perftests/etc/chartdefs/1030-BatchSize-Equal.chartdef
index bf55750..1b37d50 100644
--- a/java/perftests/etc/chartdefs/1030-BatchSize-Equal.chartdef
+++ b/java/perftests/etc/chartdefs/1030-BatchSize-Equal.chartdef
@@ -20,7 +20,7 @@
 chartType=XYLINE
 chartTitle=Transaction Batch Sizes Equal
 chartSubtitle=Persistent 1KB messages
-chartDescription=1P 1C, persistent, transacted with message payload 1KB with producer/consumer batch size varying between 1-400 messages for both P and C
+chartDescription=1P 1C, persistent, transacted with message payload 1KB with producer/consumer batch size varying between 1-400 messages for both P and C, single queue.
 
 xAxisTitle=Batch Size
 yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1031-BatchSize-Unequal.chartdef b/java/perftests/etc/chartdefs/1031-BatchSize-Unequal.chartdef
index 5f846c6..cd72663 100644
--- a/java/perftests/etc/chartdefs/1031-BatchSize-Unequal.chartdef
+++ b/java/perftests/etc/chartdefs/1031-BatchSize-Unequal.chartdef
@@ -20,7 +20,7 @@
 chartType=XYLINE
 chartTitle=Transaction Batch Size Unequal
 chartSubtitle=Persistent 1KB messages
-chartDescription=1P 1C, persistent, transacted with message payload 1KB with fixed batch size 1 for one party whilst other varies between 1-400 messages
+chartDescription=1P 1C, persistent, transacted with message payload 1KB with fixed batch size 1 for one party whilst other varies between 1-400 messages, single queue.
 
 xAxisTitle=Batch Size
 yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1040-QueueTypes.chartdef b/java/perftests/etc/chartdefs/1040-QueueTypes.chartdef
index 248db49..3ba42e2 100644
--- a/java/perftests/etc/chartdefs/1040-QueueTypes.chartdef
+++ b/java/perftests/etc/chartdefs/1040-QueueTypes.chartdef
@@ -20,7 +20,7 @@
 chartType=BAR
 chartTitle=Queue Types
 chartSubtitle=Persistent 1KB messages
-chartDescription=1P 1C, persistent, auto-ack with message payload 1KB. Sorted queue - 160,000 random keys, Priority - iteriates priority 0..9.
+chartDescription=1P 1C, persistent, auto-ack with message payload 1KB. Sorted queue - 160,000 random keys, Priority - iteriates priority 0..9, single queue.
 
 xAxisTitle=Queue Types
 yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1050-VaryingNumberOfProducerSessionsSingleConnection.chartdef b/java/perftests/etc/chartdefs/1050-VaryingNumberOfProducerSessionsSingleConnection.chartdef
index 50816a8..c92974d 100644
--- a/java/perftests/etc/chartdefs/1050-VaryingNumberOfProducerSessionsSingleConnection.chartdef
+++ b/java/perftests/etc/chartdefs/1050-VaryingNumberOfProducerSessionsSingleConnection.chartdef
@@ -20,7 +20,7 @@
 chartType=XYLINE
 chartTitle=Varying number of producer sessions on single connection
 chartSubtitle=Persistent messages (1024b)
-chartDescription=1-80P transacted on single connection, 20C transacted on separate connections, persistent, message payload 1KB.
+chartDescription=1-80P transacted on single connection, 20C transacted on separate connections, persistent, message payload 1KB, single queue.
 
 xAxisTitle=Number of producer sessions
 yAxisTitle=Throughput (KB/s)
diff --git a/java/perftests/etc/chartdefs/1300-QueueConsumersWithNonOverlappingSelectors-Transient.chartdef b/java/perftests/etc/chartdefs/1300-QueueConsumersWithNonOverlappingSelectors-Transient.chartdef
index 67821b8..95f717a 100644
--- a/java/perftests/etc/chartdefs/1300-QueueConsumersWithNonOverlappingSelectors-Transient.chartdef
+++ b/java/perftests/etc/chartdefs/1300-QueueConsumersWithNonOverlappingSelectors-Transient.chartdef
@@ -22,7 +22,7 @@
 chartSubtitle=Transient 1KB messages
 xAxisTitle=Consumers
 yAxisTitle=Throughput (messages/s)
-chartDescription=Impact of non-overlapping selectors on queue consumers with transient messages, auto-ack, message payload of 1024 bytes, 1 producer, varying  number of consumers from 1 to 32.
+chartDescription=Impact of non-overlapping selectors on queue consumers with transient messages, auto-ack, message payload of 1024 bytes, 1 producer, varying  number of consumers from 1 to 32, single queue.
 
 series.1.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM QueueConsumersWithNonOverlappingSelectors WHERE participantName = 'All' and testName like '%non overlapping - NON_PERSISTENT%'
 series.1.legend=Current
diff --git a/java/perftests/etc/chartdefs/1301-QueueConsumersWithNonOverlappingSelectors-Persistent.chartdef b/java/perftests/etc/chartdefs/1301-QueueConsumersWithNonOverlappingSelectors-Persistent.chartdef
index 7fbf55a..302b508 100644
--- a/java/perftests/etc/chartdefs/1301-QueueConsumersWithNonOverlappingSelectors-Persistent.chartdef
+++ b/java/perftests/etc/chartdefs/1301-QueueConsumersWithNonOverlappingSelectors-Persistent.chartdef
@@ -22,7 +22,7 @@
 chartSubtitle=Persistent 1KB messages
 xAxisTitle=Consumers
 yAxisTitle=Throughput (messages/s)
-chartDescription=Impact of non-overlapping selectors on queue consumers with persistent messages, auto-ack, message payload of 1024 bytes, 1 producer, varying number of consumers from 1 to 32..
+chartDescription=Impact of non-overlapping selectors on queue consumers with persistent messages, auto-ack, message payload of 1024 bytes, 1 producer, varying number of consumers from 1 to 32, single queue.
 
 
 series.1.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM QueueConsumersWithNonOverlappingSelectors WHERE participantName = 'All' and testName like '%non overlapping - PERSISTENT'
diff --git a/java/perftests/etc/chartdefs/1302-QueueConsumersWithOverlappingSelectors-Transient.chartdef b/java/perftests/etc/chartdefs/1302-QueueConsumersWithOverlappingSelectors-Transient.chartdef
index 1734265..c0796ca 100644
--- a/java/perftests/etc/chartdefs/1302-QueueConsumersWithOverlappingSelectors-Transient.chartdef
+++ b/java/perftests/etc/chartdefs/1302-QueueConsumersWithOverlappingSelectors-Transient.chartdef
@@ -22,7 +22,7 @@
 chartSubtitle=Transient 1KB messages
 xAxisTitle=Consumers
 yAxisTitle=Throughput (messages/s)
-chartDescription=Impact of 50%-overlapping selectors in queue consumers with transient messages, auto-ack, message payload 1KB, 1 producer, varying number of consumers from 2 to 32.
+chartDescription=Impact of 50%-overlapping selectors in queue consumers with transient messages, auto-ack, message payload 1KB, 1 producer, varying number of consumers from 2 to 32, single queue.
 
 series.1.statement=SELECT totalNumberOfConsumers,throughputMessagesPerS FROM QueueConsumersWithOverlappingSelectors WHERE participantName = 'All' and testName like '%50_ overlapping - NON_PERSISTENT%'
 series.1.legend=Current
diff --git a/java/perftests/etc/chartdefs/1303-QueueConsumersWithOverlappingSelectors-Persistent.chartdef b/java/perftests/etc/chartdefs/1303-QueueConsumersWithOverlappingSelectors-Persistent.chartdef
index ef7beb2..a2c75c1 100644
--- a/java/perftests/etc/chartdefs/1303-QueueConsumersWithOverlappingSelectors-Persistent.chartdef
+++ b/java/perftests/etc/chartdefs/1303-QueueConsumersWithOverlappingSelectors-Persistent.chartdef
@@ -19,7 +19,7 @@
 
 chartType=XYLINE
 chartTitle=Impact of 50%-overlapping selectors in queue consumers with persistent messages
-chartDescription=Impact of 50%-overlapping selectors in queue consumers with persistent messages, auto-ack, message payload of 1KB, 1 producer, varying number of consumers from 2 to 32.
+chartDescription=Impact of 50%-overlapping selectors in queue consumers with persistent messages, auto-ack, message payload of 1KB, 1 producer, varying number of consumers from 2 to 32, single queue.
 chartSubtitle=Persistent 1KB messages
 xAxisTitle=Consumers
 yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1500-Topic-NumberOfConsumers.chartdef b/java/perftests/etc/chartdefs/1500-Topic-NumberOfConsumers.chartdef
index ef82fdf..96f0ce3 100644
--- a/java/perftests/etc/chartdefs/1500-Topic-NumberOfConsumers.chartdef
+++ b/java/perftests/etc/chartdefs/1500-Topic-NumberOfConsumers.chartdef
@@ -20,7 +20,7 @@
 chartType=XYLINE
 chartTitle=Number of topic consumers
 chartSubtitle=Transient 1KB messages
-chartDescription=1P 1-100C transient, transacted, with message payload 1KB.
+chartDescription=1P 1-100C transient, transacted, with message payload 1KB, single queue.
 
 xAxisTitle=Numer of consumers
 yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1501-Topic-NumberOfTopics.chartdef b/java/perftests/etc/chartdefs/1501-Topic-NumberOfTopics.chartdef
index 394b232..5eac3d9 100644
--- a/java/perftests/etc/chartdefs/1501-Topic-NumberOfTopics.chartdef
+++ b/java/perftests/etc/chartdefs/1501-Topic-NumberOfTopics.chartdef
@@ -20,7 +20,7 @@
 chartType=XYLINE
 chartTitle=Number of topics
 chartSubtitle=Transient 1KB messages
-chartDescription=1,10,50,100 PC, transient, transacted, with each PC pair having own topic, message payload 1KB.
+chartDescription=1,10,50,100 PC, transient, transacted, with each PC pair having own topic, message payload 1KB, single topic.
 
 xAxisTitle=Numer of topics
 yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1502-Topic-Persistence.chartdef b/java/perftests/etc/chartdefs/1502-Topic-Persistence.chartdef
index c418709..25e64ea 100644
--- a/java/perftests/etc/chartdefs/1502-Topic-Persistence.chartdef
+++ b/java/perftests/etc/chartdefs/1502-Topic-Persistence.chartdef
@@ -20,7 +20,7 @@
 chartType=BAR
 chartTitle=Topic transient/durable subscriptions
 chartSubtitle=1KB messages
-chartDescription=1P 10C, transacted, message payload 1KB, transient messages on non-durable sub, persistent messages on durable sub
+chartDescription=1P 10C, transacted, message payload 1KB, transient messages on non-durable sub, persistent messages on durable sub, single topic,
 
 xAxisTitle=Subscription type (true durable, false non durable)
 yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1503-Topic-AckModes.chartdef b/java/perftests/etc/chartdefs/1503-Topic-AckModes.chartdef
index f25dd89..8d549ab 100644
--- a/java/perftests/etc/chartdefs/1503-Topic-AckModes.chartdef
+++ b/java/perftests/etc/chartdefs/1503-Topic-AckModes.chartdef
@@ -20,7 +20,7 @@
 chartType=BAR
 chartTitle=Topic acknowledge modes
 chartSubtitle=Transient 1KB messages
-chartDescription=1P 10C, transient, non-durable subscription, message payload 1KB
+chartDescription=1P 10C, transient, non-durable subscription, message payload 1KB, single topic.
 
 xAxisTitle=Ack Mode (0=transaction 1=auto-ack)
 yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/2001-Latency-MessageSize-Transient.chartdef b/java/perftests/etc/chartdefs/2001-Latency-MessageSize-Transient.chartdef
index 6b79391..bd252d1 100644
--- a/java/perftests/etc/chartdefs/2001-Latency-MessageSize-Transient.chartdef
+++ b/java/perftests/etc/chartdefs/2001-Latency-MessageSize-Transient.chartdef
@@ -20,7 +20,7 @@
 chartType=STATISTICAL_BAR
 chartTitle=Impact of message size on latency
 chartSubtitle=Transient messages
-chartDescription=1P 1C, transient, auto-ack, with message payload between 256-262144 bytes.
+chartDescription=1P 1C, transient, auto-ack, with message payload between 256-262144 bytes, single queue.
 
 xAxisTitle=Message Size (B)
 yAxisTitle=Latency (millis)
diff --git a/java/perftests/etc/chartdefs/2002-Latency-MessageSize-Persistent.chartdef b/java/perftests/etc/chartdefs/2002-Latency-MessageSize-Persistent.chartdef
index c04e393..36acdb6 100644
--- a/java/perftests/etc/chartdefs/2002-Latency-MessageSize-Persistent.chartdef
+++ b/java/perftests/etc/chartdefs/2002-Latency-MessageSize-Persistent.chartdef
@@ -20,7 +20,7 @@
 chartType=STATISTICAL_BAR
 chartTitle=Impact of message size on latency
 chartSubtitle=Persistent messages
-chartDescription=1P 1C, persistent, auto-ack, with message payload between 256-262144 bytes.
+chartDescription=1P 1C, persistent, auto-ack, with message payload between 256-262144 bytes, single queue.
 
 xAxisTitle=Message Size (B)
 yAxisTitle=Latency (millis)
diff --git a/java/perftests/etc/chartdefs/2031-Latency-VaryingNumberOfParticipants.chartdef b/java/perftests/etc/chartdefs/2031-Latency-VaryingNumberOfParticipants.chartdef
index fa688fe..bb19eb2 100644
--- a/java/perftests/etc/chartdefs/2031-Latency-VaryingNumberOfParticipants.chartdef
+++ b/java/perftests/etc/chartdefs/2031-Latency-VaryingNumberOfParticipants.chartdef
@@ -20,7 +20,7 @@
 chartType=STATISTICAL_BAR
 chartTitle=Latency, varying number of participants
 chartSubtitle=Persistent 1KB messages
-chartDescription=1,2,5,10 P/Cs, persistent, auto-ack, with message payload 1KB.
+chartDescription=1,2,5,10 P/Cs, persistent, auto-ack, with message payload 1KB, single queue.
 
 xAxisTitle=Consumers
 yAxisTitle=Latency (millis)
diff --git a/java/perftests/etc/testdefs/Latency-MessageSize.json b/java/perftests/etc/testdefs/Latency-MessageSize.json
index 4486d7a..f93d1ec 100644
--- a/java/perftests/etc/testdefs/Latency-MessageSize.json
+++ b/java/perftests/etc/testdefs/Latency-MessageSize.json
@@ -136,7 +136,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session1",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_producers": [
                     {
                       "_name": "Producer1",
@@ -160,7 +160,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session1",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_consumers": [
                     {
                       "_name": "Consumer1",
diff --git a/java/perftests/etc/testdefs/Latency-VaryingNumberOfParticipants.json b/java/perftests/etc/testdefs/Latency-VaryingNumberOfParticipants.json
index aefd51d..50f00a8 100644
--- a/java/perftests/etc/testdefs/Latency-VaryingNumberOfParticipants.json
+++ b/java/perftests/etc/testdefs/Latency-VaryingNumberOfParticipants.json
@@ -18,7 +18,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session1",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_producers": [
                     {
                       "_name": "Producer1",
@@ -43,7 +43,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session1",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_consumers": [
                     {
                       "_name": "Consumer1",
@@ -79,7 +79,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session1",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_producers": [
                     {
                       "_name": "Producer1",
@@ -99,7 +99,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session2",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_producers": [
                     {
                       "_name": "Producer2",
@@ -119,7 +119,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session3",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_producers": [
                     {
                       "_name": "Producer3",
@@ -139,7 +139,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session4",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_producers": [
                     {
                       "_name": "Producer4",
@@ -159,7 +159,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session5",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_producers": [
                     {
                       "_name": "Producer5",
@@ -179,7 +179,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session6",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_producers": [
                     {
                       "_name": "Producer6",
@@ -199,7 +199,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session7",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_producers": [
                     {
                       "_name": "Producer7",
@@ -219,7 +219,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session8",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_producers": [
                     {
                       "_name": "Producer8",
@@ -239,7 +239,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session9",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_producers": [
                     {
                       "_name": "Producer9",
@@ -259,7 +259,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session10",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_producers": [
                     {
                       "_name": "Producer10",
@@ -284,7 +284,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session1",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_consumers": [
                     {
                       "_name": "Consumer1",
@@ -319,7 +319,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session1",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_producers": [
                     {
                       "_name": "Producer1",
@@ -339,7 +339,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session2",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_producers": [
                     {
                       "_name": "Producer2",
@@ -359,7 +359,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session3",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_producers": [
                     {
                       "_name": "Producer3",
@@ -379,7 +379,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session4",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_producers": [
                     {
                       "_name": "Producer4",
@@ -399,7 +399,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session5",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_producers": [
                     {
                       "_name": "Producer5",
@@ -419,7 +419,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session6",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_producers": [
                     {
                       "_name": "Producer6",
@@ -439,7 +439,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session7",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_producers": [
                     {
                       "_name": "Producer7",
@@ -459,7 +459,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session8",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_producers": [
                     {
                       "_name": "Producer8",
@@ -479,7 +479,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session9",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_producers": [
                     {
                       "_name": "Producer9",
@@ -499,7 +499,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session10",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_producers": [
                     {
                       "_name": "Producer10",
@@ -524,7 +524,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session1",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_consumers": [
                     {
                       "_name": "Consumer1",
@@ -542,7 +542,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session2",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_consumers": [
                     {
                       "_name": "Consumer2",
@@ -560,7 +560,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session3",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_consumers": [
                     {
                       "_name": "Consumer3",
@@ -578,7 +578,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session4",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_consumers": [
                     {
                       "_name": "Consumer4",
@@ -596,7 +596,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session5",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_consumers": [
                     {
                       "_name": "Consumer5",
@@ -614,7 +614,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session6",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_consumers": [
                     {
                       "_name": "Consumer6",
@@ -632,7 +632,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session7",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_consumers": [
                     {
                       "_name": "Consumer7",
@@ -650,7 +650,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session8",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_consumers": [
                     {
                       "_name": "Consumer8",
@@ -668,7 +668,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session9",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_consumers": [
                     {
                       "_name": "Consumer9",
@@ -686,7 +686,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session10",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_consumers": [
                     {
                       "_name": "Consumer10",
diff --git a/java/perftests/etc/testdefs/MessageSize.json b/java/perftests/etc/testdefs/MessageSize.json
index 6d796bd..c978155 100644
--- a/java/perftests/etc/testdefs/MessageSize.json
+++ b/java/perftests/etc/testdefs/MessageSize.json
@@ -153,7 +153,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session1",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_producers": [
                     {
                       "_name": "Producer1",
@@ -177,7 +177,7 @@
               "_sessions": [
                 {
                   "_sessionName": "session1",
-                  "_acknowledgeMode": 1,
+                  "_acknowledgeMode": 0,
                   "_consumers": [
                     {
                       "_name": "Consumer1",
diff --git a/java/perftests/etc/testdefs/QueueConsumersWithNonOverlappingSelectors.js b/java/perftests/etc/testdefs/QueueConsumersWithNonOverlappingSelectors.js
index 0dd45b0..72b77e0 100644
--- a/java/perftests/etc/testdefs/QueueConsumersWithNonOverlappingSelectors.js
+++ b/java/perftests/etc/testdefs/QueueConsumersWithNonOverlappingSelectors.js
@@ -25,11 +25,11 @@
 for (var i=0; i<2; i++)
 {
     var deliveryMode = i+1;
+    var acknowledgeMode = ((i==0) ? 1 : 0);
     var durable = (deliveryMode == 2);
     var suffix = durable ? "PERSISTENT" : "NON-PERSISTENT";
     var queueName = "direct://amq.direct//queue-selectors-" + suffix + "?durable='" + durable + "'";
     var consumerNumbers = [1, 2, 4, 8, 16, 32];
-    var consumerAcknowledgeMode = 1;
     for (var j=0; j<consumerNumbers.length; j++)
     {
         var consumerNumber = consumerNumbers[j];
@@ -70,7 +70,7 @@
                         "_sessions": [
                           {
                             "_sessionName": "session1",
-                            "_acknowledgeMode": 1,
+                            "_acknowledgeMode": acknowledgeMode,
                             "_producers": [
                               {
                                 "_name": "Producer1",
@@ -100,7 +100,7 @@
                     "_sessions": [
                       {
                         "_sessionName": "session" + n,
-                        "_acknowledgeMode": consumerAcknowledgeMode,
+                        "_acknowledgeMode": acknowledgeMode,
                         "_consumers": [
                           {
                             "_name": "Consumer" + n,
diff --git a/java/perftests/etc/testdefs/QueueConsumersWithOverlappingSelectors.js b/java/perftests/etc/testdefs/QueueConsumersWithOverlappingSelectors.js
index 20cfb4a..e4c076b 100644
--- a/java/perftests/etc/testdefs/QueueConsumersWithOverlappingSelectors.js
+++ b/java/perftests/etc/testdefs/QueueConsumersWithOverlappingSelectors.js
@@ -26,6 +26,7 @@
 {
     var deliveryMode = i+1;
     var durable = (deliveryMode == 2);
+    var acknowledgeMode = ((i==0) ? 1 : 0);
     var suffix = durable ? "PERSISTENT" : "NON-PERSISTENT";
     var queueName = "direct://amq.direct//queue-selectors-overlapping-" + suffix + "?durable='" + durable + "'";
     var consumerNumbers = [2, 4, 8, 16, 32];
@@ -70,7 +71,7 @@
                         "_sessions": [
                           {
                             "_sessionName": "session1",
-                            "_acknowledgeMode": 1,
+                            "_acknowledgeMode": acknowledgeMode,
                             "_producers": [
                               {
                                 "_name": "Producer1",
@@ -111,7 +112,7 @@
                     "_sessions": [
                       {
                         "_sessionName": "session" + n,
-                        "_acknowledgeMode": consumerAcknowledgeMode,
+                        "_acknowledgeMode": acknowledgeMode,
                         "_consumers": [
                           {
                             "_name": "Consumer" + n,
diff --git a/java/perftests/pom.xml b/java/perftests/pom.xml
index c395069..7787c82 100644
--- a/java/perftests/pom.xml
+++ b/java/perftests/pom.xml
@@ -156,6 +156,48 @@
           <skip>true</skip>
         </configuration>
       </plugin>
+
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>exec-maven-plugin</artifactId>
+        <version>1.3.2</version>
+        <executions>
+          <execution>
+            <goals>
+              <goal>java</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <mainClass>org.apache.qpid.disttest.ControllerRunner</mainClass>
+          <includePluginDependencies>true</includePluginDependencies>
+          <arguments>
+            <argument>jndi-config=${basedir}/etc/perftests-jndi.properties</argument>
+            <argument>test-config=${basedir}/etc/testdefs</argument>
+            <argument>distributed=false</argument>
+            <argument>writeToDb=false</argument>
+          </arguments>
+          <systemProperties>
+            <systemProperty>
+              <key>qpid.amqp</key><value>0-91</value>
+            </systemProperty>
+            <systemProperty>
+              <key>qpid.dest_syntax</key><value>BURL</value>
+            </systemProperty>
+            <systemProperty>
+              <key>qpid.disttest.duration</key><value>5000</value>
+            </systemProperty>
+          </systemProperties>
+        </configuration>
+        <dependencies>
+          <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-jms_1.1_spec</artifactId>
+            <version>${geronimo-jms-1-1-version}</version>
+          </dependency>
+        </dependencies>
+      </plugin>
+
     </plugins>
 
   </build>
diff --git a/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/TestFileUtils.java b/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/TestFileUtils.java
index 26bbe15..0023103 100644
--- a/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/TestFileUtils.java
+++ b/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/TestFileUtils.java
@@ -121,33 +121,38 @@
         File file = createTempFile(testcase, suffix);
         if (content != null)
         {
-            FileOutputStream fos =  null;
-            try
+            saveTextContentInFile(content, file);
+        }
+        return file;
+    }
+
+    public static void saveTextContentInFile(String content, File file)
+    {
+        FileOutputStream fos =  null;
+        try
+        {
+            fos = new FileOutputStream(file);
+            fos.write(content.getBytes("UTF-8"));
+            fos.flush();
+        }
+        catch (Exception e)
+        {
+            throw new RuntimeException("Cannot add the content into temp file " + file.getAbsolutePath(), e);
+        }
+        finally
+        {
+            if (fos != null)
             {
-                fos = new FileOutputStream(file);
-                fos.write(content.getBytes("UTF-8"));
-                fos.flush();
-            }
-            catch (Exception e)
-            {
-                throw new RuntimeException("Cannot add the content into temp file " + file.getAbsolutePath(), e);
-            }
-            finally
-            {
-                if (fos != null)
+                try
                 {
-                    try
-                    {
-                        fos.close();
-                    }
-                    catch (IOException e)
-                    {
-                        throw new RuntimeException("Cannot close output stream into temp file " + file.getAbsolutePath(), e);
-                    }
+                    fos.close();
+                }
+                catch (IOException e)
+                {
+                    throw new RuntimeException("Cannot close output stream into temp file " + file.getAbsolutePath(), e);
                 }
             }
         }
-        return file;
     }
 
     /**
diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java b/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java
index 70e1b27..c7bcdd2 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java
@@ -49,6 +49,7 @@
 import org.apache.qpid.server.model.AuthenticationProvider;
 import org.apache.qpid.server.model.Broker;
 import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.BrokerShutdownProvider;
 import org.apache.qpid.server.model.ConfiguredObject;
 import org.apache.qpid.server.model.GroupProvider;
 import org.apache.qpid.server.model.JsonSystemConfigImpl;
@@ -105,7 +106,8 @@
         final AbstractSystemConfig parentObject = new JsonSystemConfigImpl(taskExecutor,
                                                                mock(EventLogger.class),
                                                                mock(LogRecorder.class),
-                                                               brokerOptions);
+                                                               brokerOptions,
+                                                               mock(BrokerShutdownProvider.class));
 
         ConfiguredObjectRecordConverter converter = new ConfiguredObjectRecordConverter(BrokerModel.getInstance());
 
@@ -215,7 +217,8 @@
         final SystemConfig parentObject = configFactory.newInstance(_taskExecutor,
                                                                    mock(EventLogger.class),
                                                                    mock(LogRecorder.class),
-                                                                   brokerOptions);
+                                                                   brokerOptions,
+                                                                   mock(BrokerShutdownProvider.class));
 
         parentObject.open();
         DurableConfigurationStore configurationStore = parentObject.getConfigurationStore();
diff --git a/java/systests/src/test/java/org/apache/qpid/systest/rest/PortRestTest.java b/java/systests/src/test/java/org/apache/qpid/systest/rest/PortRestTest.java
index 8b86163..538bd3b 100644
--- a/java/systests/src/test/java/org/apache/qpid/systest/rest/PortRestTest.java
+++ b/java/systests/src/test/java/org/apache/qpid/systest/rest/PortRestTest.java
@@ -358,9 +358,9 @@
         attributes.put(Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER);
 
         int responseCode = getRestTestHelper().submitRequest("port/" + newPortName, "PUT", attributes);
-        assertEquals("Unexpected response code for port creation", 201, responseCode);
+        assertEquals("Unexpected response code for port creation", 409, responseCode);
 
-        portData = getRestTestHelper().getJsonAsSingletonList("port/" + URLDecoder.decode(newPortName, "UTF-8"));
-        Asserts.assertPortAttributes(portData, State.ERRORED);
+        List<Map<String,Object>> ports  = getRestTestHelper().getJsonAsList("port/" + URLDecoder.decode(newPortName, "UTF-8"));
+        assertTrue("Port should not be created", ports.isEmpty());
     }
 }