Merge from trunk

git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/QPID-6262-JavaBrokerNIO@1666219 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AbstractBDBMessageStore.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AbstractBDBMessageStore.java
index e8c337a..be9248c 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AbstractBDBMessageStore.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AbstractBDBMessageStore.java
@@ -51,7 +51,7 @@
 import org.apache.qpid.server.store.MessageStore;
 import org.apache.qpid.server.store.StorableMessageMetaData;
 import org.apache.qpid.server.store.StoreException;
-import org.apache.qpid.server.store.StoreFuture;
+import org.apache.qpid.server.util.FutureResult;
 import org.apache.qpid.server.store.StoredMessage;
 import org.apache.qpid.server.store.TransactionLogResource;
 import org.apache.qpid.server.store.Xid;
@@ -924,14 +924,14 @@
      *
      * @throws org.apache.qpid.server.store.StoreException If the operation fails for any reason.
      */
-    private StoreFuture commitTranImpl(final Transaction tx, boolean syncCommit) throws StoreException
+    private FutureResult commitTranImpl(final Transaction tx, boolean syncCommit) throws StoreException
     {
         if (tx == null)
         {
             throw new StoreException("Fatal internal error: transactional is null at commitTran");
         }
 
-        StoreFuture result = getEnvironmentFacade().commit(tx, syncCommit);
+        FutureResult result = getEnvironmentFacade().commit(tx, syncCommit);
 
         if (getLogger().isDebugEnabled())
         {
@@ -1386,7 +1386,7 @@
             }
         }
 
-        synchronized StoreFuture flushToStore()
+        synchronized FutureResult flushToStore()
         {
             if(!stored())
             {
@@ -1407,7 +1407,7 @@
 
                 storedSizeChangeOccurred(getMetaData().getContentSize());
             }
-            return StoreFuture.IMMEDIATE_FUTURE;
+            return FutureResult.IMMEDIATE_FUTURE;
         }
 
         @Override
@@ -1526,14 +1526,14 @@
         }
 
         @Override
-        public StoreFuture commitTranAsync() throws StoreException
+        public FutureResult commitTranAsync() throws StoreException
         {
             checkMessageStoreOpen();
             doPreCommitActions();
             AbstractBDBMessageStore.this.storedSizeChangeOccurred(_storeSizeIncrease);
-            StoreFuture storeFuture = AbstractBDBMessageStore.this.commitTranImpl(_txn, false);
+            FutureResult futureResult = AbstractBDBMessageStore.this.commitTranImpl(_txn, false);
             doPostCommitActions();
-            return storeFuture;
+            return futureResult;
         }
 
         @Override
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/CoalescingCommiter.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/CoalescingCommiter.java
index 9643358..2a8cf92 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/CoalescingCommiter.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/CoalescingCommiter.java
@@ -22,6 +22,7 @@
 
 import java.util.Queue;
 import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import com.sleepycat.je.DatabaseException;
@@ -29,7 +30,7 @@
 import com.sleepycat.je.Transaction;
 import org.apache.log4j.Logger;
 
-import org.apache.qpid.server.store.StoreFuture;
+import org.apache.qpid.server.util.FutureResult;
 
 public class CoalescingCommiter implements Committer
 {
@@ -65,16 +66,16 @@
     }
 
     @Override
-    public StoreFuture commit(Transaction tx, boolean syncCommit)
+    public FutureResult commit(Transaction tx, boolean syncCommit)
     {
-        BDBCommitFuture commitFuture = new BDBCommitFuture(_commitThread, tx, syncCommit);
+        BDBCommitFutureResult commitFuture = new BDBCommitFutureResult(_commitThread, tx, syncCommit);
         commitFuture.commit();
         return commitFuture;
     }
 
-    private static final class BDBCommitFuture implements StoreFuture
+    private static final class BDBCommitFutureResult implements FutureResult
     {
-        private static final Logger LOGGER = Logger.getLogger(BDBCommitFuture.class);
+        private static final Logger LOGGER = Logger.getLogger(BDBCommitFutureResult.class);
 
         private final CommitThread _commitThread;
         private final Transaction _tx;
@@ -82,7 +83,7 @@
         private RuntimeException _databaseException;
         private boolean _complete;
 
-        public BDBCommitFuture(CommitThread commitThread, Transaction tx, boolean syncCommit)
+        public BDBCommitFutureResult(CommitThread commitThread, Transaction tx, boolean syncCommit)
         {
             _commitThread = commitThread;
             _tx = tx;
@@ -162,13 +163,47 @@
                 LOGGER.debug("waitForCompletion returning after " + duration + " ms for transaction " + _tx);
             }
         }
+
+        public synchronized void waitForCompletion(long timeout) throws TimeoutException
+        {
+            long startTime= System.currentTimeMillis();
+            long remaining = timeout;
+
+            while (!isComplete() && remaining > 0)
+            {
+                _commitThread.explicitNotify();
+                try
+                {
+                    wait(remaining);
+                }
+                catch (InterruptedException e)
+                {
+                    throw new RuntimeException(e);
+                }
+                if(!isComplete())
+                {
+                    remaining = (startTime + timeout) - System.currentTimeMillis();
+                }
+            }
+
+            if(remaining < 0l)
+            {
+                throw new TimeoutException("commit did not occur within given timeout period: " + timeout);
+            }
+
+            if(LOGGER.isDebugEnabled())
+            {
+                long duration = System.currentTimeMillis() - startTime;
+                LOGGER.debug("waitForCompletion returning after " + duration + " ms for transaction " + _tx);
+            }
+        }
     }
 
     /**
-     * Implements a thread which batches and commits a queue of {@link BDBCommitFuture} operations. The commit operations
+     * Implements a thread which batches and commits a queue of {@link org.apache.qpid.server.store.berkeleydb.CoalescingCommiter.BDBCommitFutureResult} operations. The commit operations
      * themselves are responsible for adding themselves to the queue and waiting for the commit to happen before
      * continuing, but it is the responsibility of this thread to tell the commit operations when they have been
-     * completed by calling back on their {@link BDBCommitFuture#complete()} and {@link BDBCommitFuture#abort} methods.
+     * completed by calling back on their {@link org.apache.qpid.server.store.berkeleydb.CoalescingCommiter.BDBCommitFutureResult#complete()} and {@link org.apache.qpid.server.store.berkeleydb.CoalescingCommiter.BDBCommitFutureResult#abort} methods.
      *
      * <p/><table id="crc"><caption>CRC Card</caption> <tr><th> Responsibilities <th> Collaborations </table>
      */
@@ -177,7 +212,7 @@
         private static final Logger LOGGER = Logger.getLogger(CommitThread.class);
 
         private final AtomicBoolean _stopped = new AtomicBoolean(false);
-        private final Queue<BDBCommitFuture> _jobQueue = new ConcurrentLinkedQueue<BDBCommitFuture>();
+        private final Queue<BDBCommitFutureResult> _jobQueue = new ConcurrentLinkedQueue<BDBCommitFutureResult>();
         private final Object _lock = new Object();
         private final EnvironmentFacade _environmentFacade;
 
@@ -244,7 +279,7 @@
 
                 for(int i = 0; i < size; i++)
                 {
-                    BDBCommitFuture commit = _jobQueue.poll();
+                    BDBCommitFutureResult commit = _jobQueue.poll();
                     if (commit == null)
                     {
                         break;
@@ -261,7 +296,7 @@
 
                     for(int i = 0; i < size; i++)
                     {
-                        BDBCommitFuture commit = _jobQueue.poll();
+                        BDBCommitFutureResult commit = _jobQueue.poll();
                         if (commit == null)
                         {
                             break;
@@ -290,7 +325,7 @@
             return !_jobQueue.isEmpty();
         }
 
-        public void addJob(BDBCommitFuture commit, final boolean sync)
+        public void addJob(BDBCommitFutureResult commit, final boolean sync)
         {
             if (_stopped.get())
             {
@@ -313,7 +348,7 @@
             {
                 _stopped.set(true);
                 Environment environment = _environmentFacade.getEnvironment();
-                BDBCommitFuture commit;
+                BDBCommitFutureResult commit;
                 if (environment != null && environment.isValid())
                 {
                     environment.flushLog(true);
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/CommitThreadWrapper.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/CommitThreadWrapper.java
index 1f05dca..133a0ee 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/CommitThreadWrapper.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/CommitThreadWrapper.java
@@ -22,16 +22,17 @@
 
 import java.util.Queue;
 import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicBoolean;
 
-import org.apache.log4j.Logger;
-import org.apache.qpid.server.store.StoreException;
-import org.apache.qpid.server.store.StoreFuture;
-
 import com.sleepycat.je.CheckpointConfig;
 import com.sleepycat.je.DatabaseException;
 import com.sleepycat.je.Environment;
 import com.sleepycat.je.Transaction;
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.server.store.StoreException;
+import org.apache.qpid.server.util.FutureResult;
 
 public class CommitThreadWrapper
 {
@@ -53,16 +54,16 @@
         _commitThread.join();
     }
 
-    public StoreFuture commit(Transaction tx, boolean syncCommit)
+    public FutureResult commit(Transaction tx, boolean syncCommit)
     {
-        BDBCommitFuture commitFuture = new BDBCommitFuture(_commitThread, tx, syncCommit);
+        BDBCommitFutureResult commitFuture = new BDBCommitFutureResult(_commitThread, tx, syncCommit);
         commitFuture.commit();
         return commitFuture;
     }
 
-    private static final class BDBCommitFuture implements StoreFuture
+    private static final class BDBCommitFutureResult implements FutureResult
     {
-        private static final Logger LOGGER = Logger.getLogger(BDBCommitFuture.class);
+        private static final Logger LOGGER = Logger.getLogger(BDBCommitFutureResult.class);
 
         private final CommitThread _commitThread;
         private final Transaction _tx;
@@ -70,7 +71,7 @@
         private boolean _complete;
         private boolean _syncCommit;
 
-        public BDBCommitFuture(CommitThread commitThread, Transaction tx, boolean syncCommit)
+        public BDBCommitFutureResult(CommitThread commitThread, Transaction tx, boolean syncCommit)
         {
             _commitThread = commitThread;
             _tx = tx;
@@ -150,13 +151,48 @@
                 LOGGER.debug("waitForCompletion returning after " + duration + " ms for transaction " + _tx);
             }
         }
+
+        @Override
+        public void waitForCompletion(final long timeout) throws TimeoutException
+        {
+            long startTime = System.currentTimeMillis();
+            long remaining = timeout;
+
+            while (!isComplete() && remaining > 0)
+            {
+                _commitThread.explicitNotify();
+                try
+                {
+                    wait(remaining);
+                }
+                catch (InterruptedException e)
+                {
+                    throw new StoreException(e);
+                }
+                if(!isComplete())
+                {
+                    remaining = (startTime + timeout) - System.currentTimeMillis();
+                }
+            }
+
+            if(remaining < 0)
+            {
+                throw new TimeoutException("Commit did not complete within required timeout: " + timeout);
+            }
+
+            if(LOGGER.isDebugEnabled())
+            {
+                long duration = System.currentTimeMillis() - startTime;
+                LOGGER.debug("waitForCompletion returning after " + duration + " ms for transaction " + _tx);
+            }
+        }
     }
 
     /**
-     * Implements a thread which batches and commits a queue of {@link BDBCommitFuture} operations. The commit operations
+     * Implements a thread which batches and commits a queue of {@link org.apache.qpid.server.store.berkeleydb.CommitThreadWrapper.BDBCommitFutureResult} operations. The commit operations
      * themselves are responsible for adding themselves to the queue and waiting for the commit to happen before
      * continuing, but it is the responsibility of this thread to tell the commit operations when they have been
-     * completed by calling back on their {@link BDBCommitFuture#complete()} and {@link BDBCommitFuture#abort} methods.
+     * completed by calling back on their {@link org.apache.qpid.server.store.berkeleydb.CommitThreadWrapper.BDBCommitFutureResult#complete()} and {@link org.apache.qpid.server.store.berkeleydb.CommitThreadWrapper.BDBCommitFutureResult#abort} methods.
      *
      * <p/><table id="crc"><caption>CRC Card</caption> <tr><th> Responsibilities <th> Collaborations </table>
      */
@@ -165,7 +201,7 @@
         private static final Logger LOGGER = Logger.getLogger(CommitThread.class);
 
         private final AtomicBoolean _stopped = new AtomicBoolean(false);
-        private final Queue<BDBCommitFuture> _jobQueue = new ConcurrentLinkedQueue<BDBCommitFuture>();
+        private final Queue<BDBCommitFutureResult> _jobQueue = new ConcurrentLinkedQueue<BDBCommitFutureResult>();
         private final CheckpointConfig _config = new CheckpointConfig();
         private final Object _lock = new Object();
         private Environment _environment;
@@ -230,7 +266,7 @@
 
                 for(int i = 0; i < size; i++)
                 {
-                    BDBCommitFuture commit = _jobQueue.poll();
+                    BDBCommitFutureResult commit = _jobQueue.poll();
                     commit.complete();
                 }
 
@@ -243,7 +279,7 @@
 
                     for(int i = 0; i < size; i++)
                     {
-                        BDBCommitFuture commit = _jobQueue.poll();
+                        BDBCommitFutureResult commit = _jobQueue.poll();
                         commit.abort(e);
                     }
                 }
@@ -268,7 +304,7 @@
             return !_jobQueue.isEmpty();
         }
 
-        public void addJob(BDBCommitFuture commit, final boolean sync)
+        public void addJob(BDBCommitFutureResult commit, final boolean sync)
         {
 
             _jobQueue.add(commit);
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/Committer.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/Committer.java
index 01e45d8..9bd1aaf 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/Committer.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/Committer.java
@@ -20,15 +20,15 @@
  */
 package org.apache.qpid.server.store.berkeleydb;
 
-import org.apache.qpid.server.store.StoreFuture;
-
 import com.sleepycat.je.Transaction;
 
+import org.apache.qpid.server.util.FutureResult;
+
 public interface Committer
 {
     void start();
 
-    StoreFuture commit(Transaction tx, boolean syncCommit);
+    FutureResult commit(Transaction tx, boolean syncCommit);
 
     void stop();
-}
\ No newline at end of file
+}
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/EnvironmentFacade.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/EnvironmentFacade.java
index a42bc43..e3969c4 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/EnvironmentFacade.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/EnvironmentFacade.java
@@ -27,14 +27,13 @@
 import com.sleepycat.je.Database;
 import com.sleepycat.je.DatabaseConfig;
 import com.sleepycat.je.DatabaseEntry;
-import com.sleepycat.je.DatabaseException;
 import com.sleepycat.je.Environment;
 import com.sleepycat.je.EnvironmentConfig;
 import com.sleepycat.je.Sequence;
 import com.sleepycat.je.SequenceConfig;
 import com.sleepycat.je.Transaction;
 
-import org.apache.qpid.server.store.StoreFuture;
+import org.apache.qpid.server.util.FutureResult;
 
 public interface EnvironmentFacade
 {
@@ -55,7 +54,7 @@
 
     Transaction beginTransaction();
 
-    StoreFuture commit(com.sleepycat.je.Transaction tx, boolean sync);
+    FutureResult commit(com.sleepycat.je.Transaction tx, boolean sync);
 
     RuntimeException handleDatabaseException(String contextMessage, RuntimeException e);
 
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacade.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacade.java
index f3a06db..eff652c 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacade.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacade.java
@@ -38,7 +38,7 @@
 import org.apache.log4j.Logger;
 
 import org.apache.qpid.server.store.StoreException;
-import org.apache.qpid.server.store.StoreFuture;
+import org.apache.qpid.server.util.FutureResult;
 import org.apache.qpid.server.store.berkeleydb.logging.Log4jLoggingHandler;
 
 public class StandardEnvironmentFacade implements EnvironmentFacade
@@ -127,7 +127,7 @@
     }
 
     @Override
-    public StoreFuture commit(com.sleepycat.je.Transaction tx, boolean syncCommit)
+    public FutureResult commit(com.sleepycat.je.Transaction tx, boolean syncCommit)
     {
         try
         {
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java
index c151a59..4c0bf41 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java
@@ -73,7 +73,7 @@
 
 import org.apache.qpid.server.configuration.IllegalConfigurationException;
 import org.apache.qpid.server.store.StoreException;
-import org.apache.qpid.server.store.StoreFuture;
+import org.apache.qpid.server.util.FutureResult;
 import org.apache.qpid.server.store.berkeleydb.BDBUtils;
 import org.apache.qpid.server.store.berkeleydb.CoalescingCommiter;
 import org.apache.qpid.server.store.berkeleydb.EnvHomeRegistry;
@@ -163,6 +163,8 @@
          * with NO_SYN durability in case if such Node crushes.
          */
         put(ReplicationConfig.LOG_FLUSH_TASK_INTERVAL, "1 min");
+
+        put(ReplicationConfig.CONSISTENCY_POLICY, "TimeConsistencyPolicy(1 s,30 s)");
     }});
 
     public static final String PERMITTED_NODE_LIST = "permittedNodes";
@@ -265,7 +267,7 @@
     }
 
     @Override
-    public StoreFuture commit(final Transaction tx, boolean syncCommit)
+    public FutureResult commit(final Transaction tx, boolean syncCommit)
     {
         try
         {
@@ -283,7 +285,7 @@
         {
             return _coalescingCommiter.commit(tx, syncCommit);
         }
-        return StoreFuture.IMMEDIATE_FUTURE;
+        return FutureResult.IMMEDIATE_FUTURE;
     }
 
     @Override
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHARemoteReplicationNodeImpl.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHARemoteReplicationNodeImpl.java
index 61a2470..002e012 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHARemoteReplicationNodeImpl.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHARemoteReplicationNodeImpl.java
@@ -24,9 +24,11 @@
 import java.util.Map;
 import java.util.Set;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 import com.sleepycat.je.rep.MasterStateException;
-
 import org.apache.log4j.Logger;
+
 import org.apache.qpid.server.configuration.IllegalConfigurationException;
 import org.apache.qpid.server.logging.EventLogger;
 import org.apache.qpid.server.logging.messages.HighAvailabilityMessages;
@@ -126,7 +128,7 @@
     }
 
     @StateTransition(currentState = {State.ACTIVE, State.UNAVAILABLE}, desiredState = State.DELETED)
-    private void doDelete()
+    private ListenableFuture<Void> doDelete()
     {
         String nodeName = getName();
 
@@ -146,6 +148,8 @@
         {
             throw new IllegalStateTransitionException("Unexpected exception on node '" + nodeName + "' deletion", e);
         }
+
+        return Futures.immediateFuture(null);
     }
 
     protected void afterSetRole()
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java
index 2000897..9f44028 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java
@@ -42,6 +42,10 @@
 
 import javax.security.auth.Subject;
 
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
 import com.sleepycat.je.DatabaseException;
 import com.sleepycat.je.LogWriteException;
 import com.sleepycat.je.rep.NodeState;
@@ -318,7 +322,7 @@
     }
 
     @Override
-    protected void activate()
+    protected ListenableFuture<Void> activate()
     {
         if (LOGGER.isDebugEnabled())
         {
@@ -352,6 +356,7 @@
                 {
                     getEventLogger().message(getGroupLogSubject(), HighAvailabilityMessages.INTRUDER_DETECTED(node.getName(), nodeAddress));
                     shutdownOnIntruder(nodeAddress);
+
                     throw new IllegalStateException("Intruder node detected: " + nodeAddress);
                 }
             }
@@ -367,24 +372,49 @@
             environmentFacade.setReplicationGroupListener(new RemoteNodesDiscoverer());
             environmentFacade.setPermittedNodes(_permittedNodes);
         }
+
+        return Futures.immediateFuture(null);
     }
 
     @StateTransition( currentState = { State.UNINITIALIZED, State.ACTIVE, State.ERRORED }, desiredState = State.STOPPED )
-    protected void doStop()
+    protected ListenableFuture<Void> doStop()
     {
-        try
-        {
-            super.doStop();
-        }
-        finally
-        {
-            closeEnvironment();
+        final SettableFuture<Void> returnVal = SettableFuture.create();
 
-            // closing the environment does not cause a state change.  Adjust the role
-            // so that our observers will see DETACHED rather than our previous role in the group.
-            _lastRole.set(NodeRole.DETACHED);
-            attributeSet(ROLE, _role, NodeRole.DETACHED);
-        }
+        ListenableFuture<Void> superFuture = super.doStop();
+        Futures.addCallback(superFuture, new FutureCallback<Void>()
+        {
+            @Override
+            public void onSuccess(final Void result)
+            {
+                doFinally();
+            }
+
+            @Override
+            public void onFailure(final Throwable t)
+            {
+                doFinally();
+            }
+
+            private void doFinally()
+            {
+                try
+                {
+                    closeEnvironment();
+
+                    // closing the environment does not cause a state change.  Adjust the role
+                    // so that our observers will see DETACHED rather than our previous role in the group.
+                    _lastRole.set(NodeRole.DETACHED);
+                    attributeSet(ROLE, _role, NodeRole.DETACHED);
+                }
+                finally
+                {
+                    returnVal.set(null);
+                }
+
+            }
+        });
+        return returnVal;
     }
 
     private void closeEnvironment()
@@ -397,43 +427,52 @@
     }
 
     @StateTransition( currentState = { State.ACTIVE, State.STOPPED, State.ERRORED}, desiredState = State.DELETED )
-    protected void doDelete()
+    protected ListenableFuture<Void> doDelete()
     {
+
         // get helpers before close. on close all children are closed and not available anymore
-        Set<InetSocketAddress> helpers = getRemoteNodeAddresses();
-        super.doDelete();
-
-        if (getConfigurationStore() != null)
+        final Set<InetSocketAddress> helpers = getRemoteNodeAddresses();
+        return doAfter(super.doDelete(),new Runnable()
         {
-            getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.DELETED());
-        }
+            @Override
+            public void run()
+            {
+                    if (getConfigurationStore() != null)
+                    {
+                        getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.DELETED());
+                    }
 
-        if (getState() == State.DELETED && !helpers.isEmpty())
-        {
-            try
-            {
-                new ReplicationGroupAdmin(_groupName, helpers).removeMember(getName());
+                    if (getState() == State.DELETED && !helpers.isEmpty())
+                    {
+                        try
+                        {
+                            new ReplicationGroupAdmin(_groupName, helpers).removeMember(getName());
+                        }
+                        catch(DatabaseException e)
+                        {
+                            LOGGER.warn("The deletion of node " + this + " on remote nodes failed due to: " + e.getMessage()
+                                        + ". To finish deletion a removal of the node from any of remote nodes (" + helpers + ") is required.");
+                        }
+                    }
+
             }
-            catch(DatabaseException e)
-            {
-                LOGGER.warn("The deletion of node " + this + " on remote nodes failed due to: " + e.getMessage()
-                        + ". To finish deletion a removal of the node from any of remote nodes (" + helpers + ") is required.");
-            }
-        }
+        });
+
+
     }
 
     @Override
-    protected void deleteVirtualHostIfExists()
+    protected ListenableFuture<Void> deleteVirtualHostIfExists()
     {
         ReplicatedEnvironmentFacade replicatedEnvironmentFacade = getReplicatedEnvironmentFacade();
         if (replicatedEnvironmentFacade != null && replicatedEnvironmentFacade.isMaster()
                 && replicatedEnvironmentFacade.getNumberOfElectableGroupMembers() == 1)
         {
-            super.deleteVirtualHostIfExists();
+            return super.deleteVirtualHostIfExists();
         }
         else
         {
-            closeVirtualHostIfExist();
+            return closeVirtualHostIfExist();
         }
     }
 
@@ -553,7 +592,7 @@
     {
         try
         {
-            closeVirtualHostIfExist();
+            closeVirtualHostIfExist().get();
 
             getConfigurationStore().upgradeStoreStructure();
 
@@ -640,7 +679,7 @@
     {
         try
         {
-            closeVirtualHostIfExist();
+            closeVirtualHostIfExist().get();
 
             Map<String, Object> hostAttributes = new HashMap<>();
             hostAttributes.put(VirtualHost.MODEL_VERSION, BrokerModel.MODEL_VERSION);
@@ -654,13 +693,24 @@
         }
     }
 
-    protected void closeVirtualHostIfExist()
+    protected ListenableFuture<Void> closeVirtualHostIfExist()
     {
-        VirtualHost<?,?,?> virtualHost = getVirtualHost();
+        final VirtualHost<?,?,?> virtualHost = getVirtualHost();
         if (virtualHost!= null)
         {
-            virtualHost.close();
-            childRemoved(virtualHost);
+            return doAfter(virtualHost.closeAsync(), new Runnable()
+            {
+                @Override
+                public void run()
+                {
+                        childRemoved(virtualHost);
+
+                }
+            });
+        }
+        else
+        {
+            return Futures.immediateFuture(null);
         }
     }
 
@@ -687,15 +737,19 @@
                         onReplica();
                         break;
                     case DETACHED:
-                        closeVirtualHostIfExist();
+                        closeVirtualHostIfExist().get();
                         break;
                     case UNKNOWN:
-                        closeVirtualHostIfExist();
+                        closeVirtualHostIfExist().get();
                         break;
                     default:
                         LOGGER.error("Unexpected state change: " + state);
                 }
             }
+            catch (InterruptedException | ExecutionException e)
+            {
+                throw new ServerScopedRuntimeException(e);
+            }
             finally
             {
                 NodeRole newRole = NodeRole.fromJeState(state);
@@ -1137,7 +1191,7 @@
 
                 try
                 {
-                    close();
+                    closeAsync();
                 }
                 finally
                 {
diff --git a/qpid/java/broker-core/pom.xml b/qpid/java/broker-core/pom.xml
index 516ac9a..e8217c8 100644
--- a/qpid/java/broker-core/pom.xml
+++ b/qpid/java/broker-core/pom.xml
@@ -107,8 +107,14 @@
       </exclusions>
     </dependency>
 
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+      <version>${guava-version}</version>
+    </dependency>
+
      <!-- test dependencies -->
-     <dependency>
+    <dependency>
       <groupId>org.apache.qpid</groupId>
       <artifactId>qpid-test-utils</artifactId>
       <version>${project.version}</version>
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java
index 6dd6c58..bc5d30a 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java
@@ -29,9 +29,13 @@
 import java.util.HashSet;
 import java.util.Properties;
 import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
 import javax.security.auth.Subject;
 
+import com.google.common.util.concurrent.ListenableFuture;
 import org.apache.log4j.LogManager;
 import org.apache.log4j.Logger;
 import org.apache.log4j.PropertyConfigurator;
@@ -106,11 +110,16 @@
             {
                 if(_systemConfig != null)
                 {
-                    _systemConfig.close();
+                    ListenableFuture<Void> closeResult = _systemConfig.closeAsync();
+                    closeResult.get(30000l, TimeUnit.MILLISECONDS);
                 }
                 _taskExecutor.stop();
 
             }
+            catch (TimeoutException | InterruptedException | ExecutionException e)
+            {
+                LOGGER.warn("Attempting to cleanly shutdown took too long, exiting immediately");
+            }
             finally
             {
                 if (_configuringOwnLogging)
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/binding/BindingImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/binding/BindingImpl.java
index c2c0cc7..06ce48f 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/binding/BindingImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/binding/BindingImpl.java
@@ -28,6 +28,9 @@
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
 import org.apache.qpid.server.configuration.IllegalConfigurationException;
 import org.apache.qpid.server.configuration.updater.VoidTask;
 import org.apache.qpid.server.exchange.AbstractExchange;
@@ -196,7 +199,7 @@
     }
 
     @StateTransition(currentState = State.ACTIVE, desiredState = State.DELETED)
-    private void doDelete()
+    private ListenableFuture<Void> doDelete()
     {
         if(_deleted.compareAndSet(false,true))
         {
@@ -209,12 +212,14 @@
 
         deleted();
         setState(State.DELETED);
+        return Futures.immediateFuture(null);
     }
 
     @StateTransition(currentState = State.UNINITIALIZED, desiredState = State.ACTIVE)
-    private void activate()
+    private ListenableFuture<Void> activate()
     {
         setState(State.ACTIVE);
+        return Futures.immediateFuture(null);
     }
 
     public void addStateChangeListener(StateChangeListener<BindingImpl,State> listener)
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/updater/TaskExecutor.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/updater/TaskExecutor.java
index e0c03fe..8d57218 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/updater/TaskExecutor.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/updater/TaskExecutor.java
@@ -21,6 +21,7 @@
 package org.apache.qpid.server.configuration.updater;
 
 import java.util.concurrent.CancellationException;
+import java.util.concurrent.Executor;
 import java.util.concurrent.Future;
 
 public interface TaskExecutor
@@ -43,4 +44,7 @@
 
     <T> Future<T> submit(Task<T> task) throws CancellationException;
 
+    boolean isTaskExecutorThread();
+
+    Executor getExecutor();
 }
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/updater/TaskExecutorImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/updater/TaskExecutorImpl.java
index 96e4e25..0f59494 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/updater/TaskExecutorImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/updater/TaskExecutorImpl.java
@@ -26,6 +26,7 @@
 import java.util.concurrent.Callable;
 import java.util.concurrent.CancellationException;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
@@ -48,6 +49,7 @@
     private volatile Thread _taskThread;
     private final AtomicBoolean _running = new AtomicBoolean();
     private volatile ExecutorService _executor;
+    private final ImmediateIfSameThreadExecutor _wrappedExecutor = new ImmediateIfSameThreadExecutor();
 
 
     @Override
@@ -67,7 +69,7 @@
                 @Override
                 public Thread newThread(Runnable r)
                 {
-                    _taskThread = new Thread(r, TASK_EXECUTION_THREAD_NAME);
+                    _taskThread = new TaskThread(r, TASK_EXECUTION_THREAD_NAME, TaskExecutorImpl.this);
                     return _taskThread;
                 }
             });
@@ -277,7 +279,13 @@
         }
     }
 
-    private boolean isTaskExecutorThread()
+    @Override
+    public Executor getExecutor()
+    {
+        return _wrappedExecutor;
+    }
+
+    public boolean isTaskExecutorThread()
     {
         return Thread.currentThread() == _taskThread;
     }
@@ -373,4 +381,41 @@
             return get();
         }
     }
+
+    private class ImmediateIfSameThreadExecutor implements Executor
+    {
+
+        @Override
+        public void execute(final Runnable command)
+        {
+            if(isTaskExecutorThread()
+               || (_executor == null && (Thread.currentThread() instanceof TaskThread
+                   && ((TaskThread)Thread.currentThread()).getTaskExecutor() == TaskExecutorImpl.this)))
+            {
+                command.run();
+            }
+            else
+            {
+                _executor.execute(command);
+            }
+
+        }
+    }
+
+    private static class TaskThread extends Thread
+    {
+
+        private final TaskExecutorImpl _taskExecutor;
+
+        public TaskThread(final Runnable r, final String name, final TaskExecutorImpl taskExecutor)
+        {
+            super(r, name);
+            _taskExecutor = taskExecutor;
+        }
+
+        public TaskExecutorImpl getTaskExecutor()
+        {
+            return _taskExecutor;
+        }
+    }
 }
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/connection/ConnectionPrincipal.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/connection/ConnectionPrincipal.java
index 82ae9f6..237a5b4 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/connection/ConnectionPrincipal.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/connection/ConnectionPrincipal.java
@@ -20,11 +20,12 @@
  */
 package org.apache.qpid.server.connection;
 
+import java.net.SocketAddress;
+
+import org.apache.qpid.server.model.VirtualHost;
 import org.apache.qpid.server.protocol.AMQConnectionModel;
 import org.apache.qpid.server.security.auth.SocketConnectionPrincipal;
 
-import java.net.SocketAddress;
-
 public class ConnectionPrincipal implements SocketConnectionPrincipal
 {
     private final AMQConnectionModel _connection;
@@ -51,6 +52,11 @@
         return _connection;
     }
 
+    public VirtualHost<?,?,?> getVirtualHost()
+    {
+        return _connection.getVirtualHost();
+    }
+
     @Override
     public boolean equals(final Object o)
     {
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java
index 883785c..a241950 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java
@@ -74,7 +74,7 @@
                 AMQConnectionModel connection = itr.next();
                 try
                 {
-                    connection.close(AMQConstant.CONNECTION_FORCED, replyText);
+                    connection.closeAsync(AMQConstant.CONNECTION_FORCED, replyText);
                 }
                 catch (Exception e)
                 {
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/consumer/AbstractConsumerTarget.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/consumer/AbstractConsumerTarget.java
index 0421a66..be4ac9d4 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/consumer/AbstractConsumerTarget.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/consumer/AbstractConsumerTarget.java
@@ -23,17 +23,21 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.CopyOnWriteArraySet;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.server.message.MessageInstance;
 import org.apache.qpid.server.util.StateChangeListener;
 
 public abstract class AbstractConsumerTarget implements ConsumerTarget
 {
-
+    private static final Logger LOGGER = Logger.getLogger(AbstractConsumerTarget.class);
     private final AtomicReference<State> _state;
 
     private final Set<StateChangeListener<ConsumerTarget, State>> _stateChangeListeners = new
@@ -41,6 +45,7 @@
 
     private final Lock _stateChangeLock = new ReentrantLock();
     private final AtomicInteger _stateActivates = new AtomicInteger();
+    private ConcurrentLinkedQueue<ConsumerMessageInstancePair> _queue = new ConcurrentLinkedQueue();
 
 
     protected AbstractConsumerTarget(final State initialState)
@@ -48,6 +53,26 @@
         _state = new AtomicReference<State>(initialState);
     }
 
+    @Override
+    public void processPending()
+    {
+        while(hasMessagesToSend())
+        {
+            sendNextMessage();
+        }
+
+        processClosed();
+    }
+
+    protected abstract void processClosed();
+
+    @Override
+    public final boolean isSuspended()
+    {
+        return getSessionModel().getConnectionModel().isMessageAssignmentSuspended() || doIsSuspended();
+    }
+
+    protected abstract boolean doIsSuspended();
 
     public final State getState()
     {
@@ -101,6 +126,7 @@
         }
     }
 
+    @Override
     public final void notifyCurrentState()
     {
 
@@ -136,4 +162,41 @@
         _stateChangeLock.unlock();
     }
 
+    @Override
+    public final long send(final ConsumerImpl consumer, MessageInstance entry, boolean batch)
+    {
+        _queue.add(new ConsumerMessageInstancePair(consumer, entry, batch));
+
+        getSessionModel().getConnectionModel().notifyWork();
+        return entry.getMessage().getSize();
+    }
+
+    protected abstract void doSend(final ConsumerImpl consumer, MessageInstance entry, boolean batch);
+
+    @Override
+    public boolean hasMessagesToSend()
+    {
+        return !_queue.isEmpty();
+    }
+
+    @Override
+    public void sendNextMessage()
+    {
+        ConsumerMessageInstancePair consumerMessage = _queue.peek();
+        if (consumerMessage != null)
+        {
+            _queue.poll();
+
+            ConsumerImpl consumer = consumerMessage.getConsumer();
+            MessageInstance entry = consumerMessage.getEntry();
+            boolean batch = consumerMessage.isBatch();
+            doSend(consumer, entry, batch);
+
+            if (consumer.acquires())
+            {
+                entry.unlockAcquisition();
+            }
+        }
+
+    }
 }
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/consumer/ConsumerImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/consumer/ConsumerImpl.java
index c0db72d..e17eca8 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/consumer/ConsumerImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/consumer/ConsumerImpl.java
@@ -22,6 +22,8 @@
 
 import java.util.concurrent.atomic.AtomicLong;
 
+import com.google.common.util.concurrent.ListenableFuture;
+
 import org.apache.qpid.server.message.MessageSource;
 import org.apache.qpid.server.protocol.AMQSessionModel;
 
@@ -31,6 +33,8 @@
 
     void externalStateChange();
 
+    ConsumerTarget getTarget();
+
     enum Option
     {
         ACQUIRES,
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/consumer/ConsumerMessageInstancePair.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/consumer/ConsumerMessageInstancePair.java
new file mode 100644
index 0000000..aa5e419
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/consumer/ConsumerMessageInstancePair.java
@@ -0,0 +1,52 @@
+/*
+ * 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.consumer;
+
+import org.apache.qpid.server.message.MessageInstance;
+
+public class ConsumerMessageInstancePair
+{
+    private final ConsumerImpl _consumer;
+    private final MessageInstance _entry;
+    private final boolean _batch;
+
+    public ConsumerMessageInstancePair(final ConsumerImpl consumer, final MessageInstance entry, final boolean batch)
+    {
+        _consumer = consumer;
+        _entry = entry;
+        _batch = batch;
+
+    }
+
+    public ConsumerImpl getConsumer()
+    {
+        return _consumer;
+    }
+
+    public MessageInstance getEntry()
+    {
+        return _entry;
+    }
+
+    public boolean isBatch()
+    {
+        return _batch;
+    }
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/consumer/ConsumerTarget.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/consumer/ConsumerTarget.java
index 5aef922..cef5667 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/consumer/ConsumerTarget.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/consumer/ConsumerTarget.java
@@ -33,6 +33,8 @@
 
     void removeStateChangeListener(StateChangeListener<ConsumerTarget, State> listener);
 
+    void processPending();
+
     enum State
     {
         ACTIVE, SUSPENDED, CLOSED
@@ -44,6 +46,8 @@
 
     void consumerRemoved(ConsumerImpl sub);
 
+    void notifyCurrentState();
+
     void addStateListener(StateChangeListener<ConsumerTarget, State> listener);
 
     long getUnacknowledgedBytes();
@@ -54,6 +58,10 @@
 
     long send(final ConsumerImpl consumer, MessageInstance entry, boolean batch);
 
+    boolean hasMessagesToSend();
+
+    void sendNextMessage();
+
     void flushBatched();
 
     void queueDeleted();
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
index cb026e1..61bbe6f 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
@@ -29,6 +29,7 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
+import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.CopyOnWriteArrayList;
@@ -36,6 +37,10 @@
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
 import org.apache.log4j.Logger;
 
 import org.apache.qpid.exchange.ExchangeDefaults;
@@ -63,12 +68,12 @@
 import org.apache.qpid.server.store.StorableMessageMetaData;
 import org.apache.qpid.server.txn.ServerTransaction;
 import org.apache.qpid.server.util.Action;
-import org.apache.qpid.server.util.ConnectionScopedRuntimeException;
 import org.apache.qpid.server.util.StateChangeListener;
 import org.apache.qpid.server.virtualhost.ExchangeIsAlternateException;
 import org.apache.qpid.server.virtualhost.RequiredExchangeException;
 import org.apache.qpid.server.virtualhost.ReservedExchangeNameException;
 import org.apache.qpid.server.virtualhost.VirtualHostImpl;
+import org.apache.qpid.server.virtualhost.VirtualHostUnavailableException;
 
 public abstract class AbstractExchange<T extends AbstractExchange<T>>
         extends AbstractConfiguredObject<T>
@@ -479,7 +484,7 @@
     {
         if (_virtualHost.getState() != State.ACTIVE)
         {
-            throw new ConnectionScopedRuntimeException("Virtualhost state " + _virtualHost.getState() + " prevents the message from being sent");
+            throw new VirtualHostUnavailableException(this._virtualHost);
         }
 
         List<? extends BaseQueue> queues = route(message, routingAddress, instanceProperties);
@@ -593,9 +598,18 @@
     }
 
     @Override
-    public boolean addBinding(String bindingKey, AMQQueue queue, Map<String, Object> arguments)
+    public boolean addBinding(final String bindingKey, final AMQQueue queue, final Map<String, Object> arguments)
     {
-        return makeBinding(null, bindingKey, queue, arguments, false);
+        return doSync(doOnConfigThread(new Callable<ListenableFuture<Boolean>>()
+        {
+            @Override
+            public ListenableFuture<Boolean> call() throws Exception
+            {
+                return makeBindingAsync(null, bindingKey, queue, arguments, false);
+            }
+        }));
+
+
     }
 
     @Override
@@ -603,12 +617,20 @@
                                   final AMQQueue queue,
                                   final Map<String, Object> arguments)
     {
-        final BindingImpl existingBinding = getBinding(bindingKey, queue);
-        return makeBinding(existingBinding == null ? null : existingBinding.getId(),
-                           bindingKey,
-                           queue,
-                           arguments,
-                           true);
+        return doSync(doOnConfigThread(new Callable<ListenableFuture<Boolean>>()
+        {
+            @Override
+            public ListenableFuture<Boolean> call() throws Exception
+            {
+
+                final BindingImpl existingBinding = getBinding(bindingKey, queue);
+                return makeBindingAsync(existingBinding == null ? null : existingBinding.getId(),
+                                   bindingKey,
+                                   queue,
+                                   arguments,
+                                   true);
+            }
+        }));
     }
 
 
@@ -634,7 +656,15 @@
             doRemoveBinding(b);
             queue.removeBinding(b);
 
-            b.delete();
+            // TODO - RG - Fix bindings!
+            if(getTaskExecutor().isTaskExecutorThread())
+            {
+                b.deleteAsync();
+            }
+            else
+            {
+                b.delete();
+            }
         }
 
     }
@@ -651,7 +681,7 @@
         return _bindingsMap.get(new BindingIdentifier(bindingKey,queue));
     }
 
-    private boolean makeBinding(UUID id,
+    private ListenableFuture<Boolean> makeBindingAsync(UUID id,
                                 String bindingKey,
                                 AMQQueue queue,
                                 Map<String, Object> arguments,
@@ -685,22 +715,45 @@
                 attributes.put(Binding.ID, id);
                 attributes.put(Binding.ARGUMENTS, arguments);
 
-                BindingImpl b = new BindingImpl(attributes, queue, this);
-                b.create(); // Must be called before addBinding as it resolves automated attributes.
+                final BindingImpl b = new BindingImpl(attributes, queue, this);
 
-                addBinding(b);
-                return true;
+                final SettableFuture<Boolean> returnVal = SettableFuture.create();
+
+                Futures.addCallback(b.createAsync(), new FutureCallback<Void>()
+                {
+                    @Override
+                    public void onSuccess(final Void result)
+                    {
+                        try
+                        {
+                            addBinding(b);
+                            returnVal.set(true);
+                        }
+                        catch(Throwable t)
+                        {
+                            returnVal.setException(t);
+                        }
+                    }
+
+                    @Override
+                    public void onFailure(final Throwable t)
+                    {
+                        returnVal.setException(t);
+                    }
+                }, getTaskExecutor().getExecutor()); // Must be called before addBinding as it resolves automated attributes.
+
+                return returnVal;
             }
             else if(force)
             {
                 Map<String,Object> oldArguments = existingMapping.getArguments();
                 existingMapping.setArguments(arguments);
                 onBindingUpdated(existingMapping, oldArguments);
-                return true;
+                return Futures.immediateFuture(true);
             }
             else
             {
-                return false;
+                return Futures.immediateFuture(false);
             }
         }
     }
@@ -723,22 +776,24 @@
 
 
     @StateTransition(currentState = {State.UNINITIALIZED,State.ERRORED}, desiredState = State.ACTIVE)
-    private void activate()
+    private ListenableFuture<Void> activate()
     {
         setState(State.ACTIVE);
+        return Futures.immediateFuture(null);
     }
 
 
     @StateTransition(currentState = State.UNINITIALIZED, desiredState = State.DELETED)
-    private void doDeleteBeforeInitialize()
+    private ListenableFuture<Void>  doDeleteBeforeInitialize()
     {
         preSetAlternateExchange();
         setState(State.DELETED);
+        return Futures.immediateFuture(null);
     }
 
 
     @StateTransition(currentState = State.ACTIVE, desiredState = State.DELETED)
-    private void doDelete()
+    private ListenableFuture<Void> doDelete()
     {
         try
         {
@@ -748,8 +803,9 @@
         }
         catch (ExchangeIsAlternateException e)
         {
-            return;
+
         }
+        return Futures.immediateFuture(null);
     }
 
     @Override
@@ -860,4 +916,5 @@
         return binding;
     }
 
+
 }
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/ExchangeImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/ExchangeImpl.java
index 3e377eb..be98665 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/ExchangeImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/ExchangeImpl.java
@@ -107,8 +107,4 @@
         void bindingRemoved(ExchangeImpl exchange, BindingImpl binding);
     }
 
-    public void addBindingListener(BindingListener listener);
-
-    public void removeBindingListener(BindingListener listener);
-
 }
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/flow/BytesOnlyCreditManager.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/flow/BytesOnlyCreditManager.java
deleted file mode 100644
index be3a13d..0000000
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/flow/BytesOnlyCreditManager.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
-*
-* 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.flow;
-
-
-import java.util.concurrent.atomic.AtomicLong;
-
-public class BytesOnlyCreditManager extends AbstractFlowCreditManager
-{
-    private final AtomicLong _bytesCredit;
-
-    public BytesOnlyCreditManager(long initialCredit)
-    {
-        _bytesCredit = new AtomicLong(initialCredit);
-    }
-
-    public long getMessageCredit()
-    {
-        return -1L;
-    }
-
-    public long getBytesCredit()
-    {
-        return _bytesCredit.get();
-    }
-
-    public void restoreCredit(long messageCredit, long bytesCredit)
-    {
-        _bytesCredit.addAndGet(bytesCredit);
-        setSuspended(false);
-    }
-
-    public void removeAllCredit()
-    {
-        _bytesCredit.set(0L);
-    }
-
-    public boolean hasCredit()
-    {
-        return _bytesCredit.get() > 0L;
-    }
-
-    public boolean useCreditForMessage(long msgSize)
-    {
-        if(hasCredit())
-        {
-            if(_bytesCredit.addAndGet(-msgSize) >= 0)
-            {
-                return true;
-            }
-            else
-            {
-                _bytesCredit.addAndGet(msgSize);
-                setSuspended(true);
-                return false;
-            }
-        }
-        else
-        {
-            return false;
-        }
-
-    }
-
-    public void setBytesCredit(long bytesCredit)
-    {
-        _bytesCredit.set( bytesCredit );
-    }
-}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/flow/FlowCreditManager.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/flow/FlowCreditManager.java
index 280f285..08aac0b 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/flow/FlowCreditManager.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/flow/FlowCreditManager.java
@@ -24,10 +24,6 @@
 
 public interface FlowCreditManager
 {
-    long getMessageCredit();
-
-    long getBytesCredit();
-
     public static interface FlowCreditManagerListener
     {
         void creditStateChanged(boolean hasCredit);
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/flow/MessageAndBytesCreditManager.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/flow/MessageAndBytesCreditManager.java
deleted file mode 100644
index 31c1fda..0000000
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/flow/MessageAndBytesCreditManager.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
-*
-* 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.flow;
-
-
-public class MessageAndBytesCreditManager extends AbstractFlowCreditManager implements FlowCreditManager
-{
-    private long _messageCredit;
-    private long _bytesCredit;
-
-    public MessageAndBytesCreditManager(final long messageCredit, final long bytesCredit)
-    {
-        _messageCredit = messageCredit;
-        _bytesCredit = bytesCredit;
-    }
-
-    public synchronized long getMessageCredit()
-    {
-        return _messageCredit;
-    }
-
-    public synchronized long getBytesCredit()
-    {
-        return _bytesCredit;
-    }
-
-    public synchronized void restoreCredit(long messageCredit, long bytesCredit)
-    {        
-        _messageCredit += messageCredit;
-        _bytesCredit += bytesCredit;
-        setSuspended(hasCredit());
-    }
-
-    public synchronized void removeAllCredit()
-    {
-        _messageCredit = 0L;
-        _bytesCredit = 0L;
-        setSuspended(true);
-    }
-
-    public synchronized boolean hasCredit()
-    {
-        return (_messageCredit > 0L) && ( _bytesCredit > 0L );
-    }
-
-    public synchronized boolean useCreditForMessage(final long msgSize)
-    {
-        if(_messageCredit == 0L)
-        {
-            setSuspended(true);
-            return false;
-        }
-        else
-        {
-            if(msgSize > _bytesCredit)
-            {
-                setSuspended(true);
-                return false;
-            }
-            _messageCredit--;
-            _bytesCredit -= msgSize;
-            setSuspended(false);
-            return true;
-        }
-        
-    }
-
-    public synchronized void setBytesCredit(long bytesCredit)
-    {
-        _bytesCredit = bytesCredit;
-    }
-}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
index e636382..529aa23 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
@@ -41,12 +41,23 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
+import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 
 import javax.security.auth.Subject;
 
+import com.google.common.util.concurrent.AbstractFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
+import com.google.common.util.concurrent.SettableFuture;
 import org.apache.log4j.Logger;
 import org.codehaus.jackson.JsonGenerator;
 import org.codehaus.jackson.JsonProcessingException;
@@ -68,6 +79,7 @@
 import org.apache.qpid.server.security.encryption.ConfigurationSecretEncrypter;
 import org.apache.qpid.server.store.ConfiguredObjectRecord;
 import org.apache.qpid.server.util.Action;
+import org.apache.qpid.server.util.FutureResult;
 import org.apache.qpid.server.util.ServerScopedRuntimeException;
 import org.apache.qpid.util.Strings;
 
@@ -162,7 +174,7 @@
 
     private final OwnAttributeResolver _attributeResolver = new OwnAttributeResolver(this);
 
-    @ManagedAttributeField( afterSet = "attainStateIfOpenedOrReopenFailed" )
+    @ManagedAttributeField
     private State _desiredState;
     private boolean _openComplete;
     private boolean _openFailed;
@@ -439,24 +451,84 @@
     @Override
     public final void open()
     {
-        if(_dynamicState.compareAndSet(DynamicState.UNINIT, DynamicState.OPENED))
-        {
-            _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);
-            }
-        }
+        doSync(openAsync());
     }
 
+
+    public final ListenableFuture<Void> openAsync()
+    {
+        return doOnConfigThread(new Callable<ListenableFuture<Void>>()
+                                {
+                                    @Override
+                                    public ListenableFuture<Void> call() throws Exception
+                                    {
+                                        if (_dynamicState.compareAndSet(DynamicState.UNINIT, DynamicState.OPENED))
+                                        {
+                                            _openFailed = false;
+                                            OpenExceptionHandler exceptionHandler = new OpenExceptionHandler();
+                                            try
+                                            {
+                                                doResolution(true, exceptionHandler);
+                                                doValidation(true, exceptionHandler);
+                                                doOpening(true, exceptionHandler);
+                                                return doAttainState(exceptionHandler);
+                                            }
+                                            catch (RuntimeException e)
+                                            {
+                                                exceptionHandler.handleException(e, AbstractConfiguredObject.this);
+                                                return Futures.immediateFuture(null);
+                                            }
+                                        }
+                                        else
+                                        {
+                                            return Futures.immediateFuture(null);
+                                        }
+
+                                    }
+                                });
+
+    }
+
+    protected final <T> ListenableFuture<T> doOnConfigThread(final Callable<ListenableFuture<T>> action)
+    {
+        final SettableFuture<T> returnVal = SettableFuture.create();
+
+        _taskExecutor.submit(new Task<Void>()
+        {
+
+            @Override
+            public Void execute()
+            {
+                try
+                {
+                    Futures.addCallback(action.call(), new FutureCallback<T>()
+                    {
+                        @Override
+                        public void onSuccess(final T result)
+                        {
+                            returnVal.set(result);
+                        }
+
+                        @Override
+                        public void onFailure(final Throwable t)
+                        {
+                            returnVal.setException(t);
+                        }
+                    });
+                }
+                catch (Exception e)
+                {
+                    returnVal.setException(e);
+                }
+                return null;
+            }
+        });
+
+        return returnVal;
+    }
+
+
+
     public void registerWithParents()
     {
         for(ConfiguredObject<?> parent : _parents.values())
@@ -468,17 +540,78 @@
         }
     }
 
-    protected void closeChildren()
+    private class ChildCounter
     {
+        private final AtomicInteger _count = new AtomicInteger();
+        private final Runnable _task;
+
+        private ChildCounter(final Runnable task)
+        {
+            _task = task;
+        }
+
+        public void incrementCount()
+        {
+            _count.incrementAndGet();
+        }
+
+        public void decrementCount()
+        {
+            if(_count.decrementAndGet() == 0)
+            {
+                _task.run();
+            }
+        }
+    }
+
+    protected final ListenableFuture<Void> closeChildren()
+    {
+        final SettableFuture<Void> returnVal = SettableFuture.create();
+        final ChildCounter counter = new ChildCounter(new Runnable()
+        {
+            @Override
+            public void run()
+            {
+                returnVal.set(null);
+                LOGGER.debug("All children closed " + AbstractConfiguredObject.this.getClass().getSimpleName() + " : " + getName() );
+
+            }
+        });
+        counter.incrementCount();
+
+
         applyToChildren(new Action<ConfiguredObject<?>>()
         {
             @Override
             public void performAction(final ConfiguredObject<?> child)
             {
-                child.close();
+                counter.incrementCount();
+                ListenableFuture<Void> close = child.closeAsync();
+                Futures.addCallback(close, new FutureCallback<Void>()
+                {
+                    @Override
+                    public void onSuccess(final Void result)
+                    {
+                        counter.decrementCount();
+                    }
+
+                    @Override
+                    public void onFailure(final Throwable t)
+                    {
+                        LOGGER.error("Exception occurred while closing "
+                                     + child.getClass().getSimpleName()
+                                     + " : '"
+                                     + child.getName()
+                                     + "'", t);
+                        // No need to decrement counter as setting the exception will complete the future
+                        returnVal.setException(t);
+                    }
+                }, MoreExecutors.sameThreadExecutor());
             }
         });
 
+        counter.decrementCount();
+
         for(Collection<ConfiguredObject<?>> childList : _children.values())
         {
             childList.clear();
@@ -494,23 +627,60 @@
             childNameMap.clear();
         }
 
+        return returnVal;
     }
 
     @Override
-    public final void close()
+    public void close()
     {
-        if(_dynamicState.compareAndSet(DynamicState.OPENED, DynamicState.CLOSED))
-        {
-            beforeClose();
-            closeChildren();
-            onClose();
-            unregister(false);
-
-        }
+        doSync(closeAsync());
     }
 
-    protected void beforeClose()
+    @Override
+    public final ListenableFuture<Void> closeAsync()
     {
+        return doOnConfigThread(new Callable<ListenableFuture<Void>>()
+        {
+            @Override
+            public ListenableFuture<Void> call() throws Exception
+            {
+                LOGGER.debug("Closing " + AbstractConfiguredObject.this.getClass().getSimpleName() + " : " + getName());
+
+                if(_dynamicState.compareAndSet(DynamicState.OPENED, DynamicState.CLOSED))
+                {
+
+                    return doAfter(beforeClose(), new Callable<ListenableFuture<Void>>()
+                    {
+                        @Override
+                        public ListenableFuture<Void> call() throws Exception
+                        {
+                            return closeChildren();
+                        }
+                    }).then(new Runnable()
+                            {
+                                @Override
+                                public void run()
+                                {
+                                    onClose();
+                                    unregister(false);
+                                    LOGGER.debug("Closed " + AbstractConfiguredObject.this.getClass().getSimpleName() + " : " + getName());
+                                }
+                            });
+                }
+                else
+                {
+                    LOGGER.debug("Closed " + AbstractConfiguredObject.this.getClass().getSimpleName() + " : " + getName());
+
+                    return Futures.immediateFuture(null);
+                }
+            }
+        });
+
+    }
+
+    protected ListenableFuture<Void> beforeClose()
+    {
+        return Futures.immediateFuture(null);
     }
 
     protected void onClose()
@@ -519,48 +689,65 @@
 
     public final void create()
     {
-        if(_dynamicState.compareAndSet(DynamicState.UNINIT, DynamicState.OPENED))
+        doSync(createAsync());
+    }
+
+    public final ListenableFuture<Void> createAsync()
+    {
+        return doOnConfigThread(new Callable<ListenableFuture<Void>>()
         {
-            final AuthenticatedPrincipal currentUser = SecurityManager.getCurrentUser();
-            if(currentUser != null)
+            @Override
+            public ListenableFuture<Void> call() throws Exception
             {
-                String currentUserName = currentUser.getName();
-                _attributes.put(LAST_UPDATED_BY, currentUserName);
-                _attributes.put(CREATED_BY, currentUserName);
-                _lastUpdatedBy = currentUserName;
-                _createdBy = currentUserName;
-            }
-            final long currentTime = System.currentTimeMillis();
-            _attributes.put(LAST_UPDATED_TIME, currentTime);
-            _attributes.put(CREATED_TIME, currentTime);
-            _lastUpdatedTime = currentTime;
-            _createdTime = currentTime;
+                if (_dynamicState.compareAndSet(DynamicState.UNINIT, DynamicState.OPENED))
+                {
+                    final AuthenticatedPrincipal currentUser = SecurityManager.getCurrentUser();
+                    if (currentUser != null)
+                    {
+                        String currentUserName = currentUser.getName();
+                        _attributes.put(LAST_UPDATED_BY, currentUserName);
+                        _attributes.put(CREATED_BY, currentUserName);
+                        _lastUpdatedBy = currentUserName;
+                        _createdBy = currentUserName;
+                    }
+                    final long currentTime = System.currentTimeMillis();
+                    _attributes.put(LAST_UPDATED_TIME, currentTime);
+                    _attributes.put(CREATED_TIME, currentTime);
+                    _lastUpdatedTime = currentTime;
+                    _createdTime = currentTime;
 
-            CreateExceptionHandler createExceptionHandler = new CreateExceptionHandler();
-            try
-            {
-                doResolution(true, createExceptionHandler);
-                doValidation(true, createExceptionHandler);
-                validateOnCreate();
-                registerWithParents();
-            }
-            catch(RuntimeException e)
-            {
-                createExceptionHandler.handleException(e, this);
-            }
+                    CreateExceptionHandler createExceptionHandler = new CreateExceptionHandler();
+                    try
+                    {
+                        doResolution(true, createExceptionHandler);
+                        doValidation(true, createExceptionHandler);
+                        validateOnCreate();
+                        registerWithParents();
+                    }
+                    catch (RuntimeException e)
+                    {
+                        createExceptionHandler.handleException(e, AbstractConfiguredObject.this);
+                    }
 
-            AbstractConfiguredObjectExceptionHandler unregisteringExceptionHandler = new CreateExceptionHandler(true);
-            try
-            {
-                doCreation(true, unregisteringExceptionHandler);
-                doOpening(true, unregisteringExceptionHandler);
-                doAttainState(unregisteringExceptionHandler);
+                    final AbstractConfiguredObjectExceptionHandler unregisteringExceptionHandler =
+                            new CreateExceptionHandler(true);
+
+                    try
+                    {
+                        doCreation(true, unregisteringExceptionHandler);
+                        doOpening(true, unregisteringExceptionHandler);
+                        return doAttainState(unregisteringExceptionHandler);
+                    }
+                    catch (RuntimeException e)
+                    {
+                        unregisteringExceptionHandler.handleException(e, AbstractConfiguredObject.this);
+                    }
+                }
+                return Futures.immediateFuture(null);
+
             }
-            catch(RuntimeException e)
-            {
-                unregisteringExceptionHandler.handleException(e, this);
-            }
-        }
+        });
+
     }
 
     protected void validateOnCreate()
@@ -610,8 +797,40 @@
     {
     }
 
-    private void doAttainState(final AbstractConfiguredObjectExceptionHandler exceptionHandler)
+    private ListenableFuture<Void> doAttainState(final AbstractConfiguredObjectExceptionHandler exceptionHandler)
     {
+        final SettableFuture<Void> returnVal = SettableFuture.create();
+        final ChildCounter counter = new ChildCounter(new Runnable()
+        {
+            @Override
+            public void run()
+            {
+                try
+                {
+                    attainState().addListener(new Runnable()
+                    {
+                        @Override
+                        public void run()
+                        {
+                            returnVal.set(null);
+                        }
+                    }, getTaskExecutor().getExecutor());
+                }
+                catch(RuntimeException e)
+                {
+                    try
+                    {
+                        exceptionHandler.handleException(e, AbstractConfiguredObject.this);
+                        returnVal.set(null);
+                    }
+                    catch(Throwable t)
+                    {
+                        returnVal.setException(t);
+                    }
+                }
+            }
+        });
+        counter.incrementCount();
         applyToChildren(new Action<ConfiguredObject<?>>()
         {
             @Override
@@ -619,22 +838,43 @@
             {
                 if (child instanceof AbstractConfiguredObject)
                 {
-                    AbstractConfiguredObject configuredObject = (AbstractConfiguredObject) child;
+                    final AbstractConfiguredObject configuredObject = (AbstractConfiguredObject) child;
                     if (configuredObject._dynamicState.get() == DynamicState.OPENED)
                     {
-                        try
-                        {
-                            configuredObject.doAttainState(exceptionHandler);
-                        }
-                        catch (RuntimeException e)
-                        {
-                            exceptionHandler.handleException(e, configuredObject);
-                        }
+                        counter.incrementCount();
+                        Futures.addCallback(configuredObject.doAttainState(exceptionHandler),
+                                            new FutureCallback()
+                                            {
+                                                @Override
+                                                public void onSuccess(final Object result)
+                                                {
+                                                    counter.decrementCount();
+                                                }
+
+                                                @Override
+                                                public void onFailure(final Throwable t)
+                                                {
+                                                    try
+                                                    {
+                                                        if (t instanceof RuntimeException)
+                                                        {
+                                                            exceptionHandler.handleException((RuntimeException) t,
+                                                                                             configuredObject);
+                                                        }
+                                                    }
+                                                    finally
+                                                    {
+                                                        counter.decrementCount();
+                                                    }
+                                                }
+                                            },getTaskExecutor().getExecutor());
+
                     }
                 }
             }
         });
-        attainState();
+        counter.decrementCount();
+        return returnVal;
     }
 
     protected void doOpening(boolean skipCheck, final AbstractConfiguredObjectExceptionHandler exceptionHandler)
@@ -890,16 +1130,17 @@
         }
     }
 
-    private void attainStateIfOpenedOrReopenFailed()
+    private ListenableFuture<Void> attainStateIfOpenedOrReopenFailed()
     {
         if (_openComplete || getDesiredState() == State.DELETED)
         {
-            attainState();
+            return attainState();
         }
         else if (_openFailed)
         {
-            open();
+            return openAsync();
         }
+        return Futures.immediateFuture(null);
     }
 
     protected void onOpen()
@@ -907,10 +1148,11 @@
 
     }
 
-    protected void attainState()
+    protected ListenableFuture<Void> attainState()
     {
         State currentState = getState();
         State desiredState = getDesiredState();
+        ListenableFuture<Void> returnVal;
         if(currentState != desiredState)
         {
             Method stateChangingMethod = getStateChangeMethod(currentState, desiredState);
@@ -918,7 +1160,7 @@
             {
                 try
                 {
-                    stateChangingMethod.invoke(this);
+                    returnVal = (ListenableFuture<Void>) stateChangingMethod.invoke(this);
                 }
                 catch (IllegalAccessException e)
                 {
@@ -938,7 +1180,16 @@
                     throw new ServerScopedRuntimeException("Unexpected checked exception when calling state transition", underlying);
                 }
             }
+            else
+            {
+                returnVal = Futures.immediateFuture(null);
+            }
         }
+        else
+        {
+            returnVal = Futures.immediateFuture(null);
+        }
+        return returnVal;
     }
 
     private Method getStateChangeMethod(final State currentState, final State desiredState)
@@ -1013,44 +1264,72 @@
     }
 
 
-    private State setDesiredState(final State desiredState)
+    private ListenableFuture<Void> setDesiredState(final State desiredState)
             throws IllegalStateTransitionException, AccessControlException
     {
-
-        return runTask(new Task<State>()
+        return doOnConfigThread(new Callable<ListenableFuture<Void>>()
+        {
+            @Override
+            public ListenableFuture<Void> call() throws Exception
+            {
+                final State state = getState();
+                final State currentDesiredState = getDesiredState();
+                if(desiredState == currentDesiredState && desiredState != state)
+                {
+                    return doAfter(attainStateIfOpenedOrReopenFailed(), new Runnable()
+                    {
+                        @Override
+                        public void run()
                         {
-                            @Override
-                            public State execute()
+                            final State currentState = getState();
+                            if (currentState != state)
                             {
-
-                                State state = getState();
-                                if(desiredState == getDesiredState() && desiredState != state)
-                                {
-                                    attainStateIfOpenedOrReopenFailed();
-                                    final State currentState = getState();
-                                    if (currentState != state)
-                                    {
-                                        notifyStateChanged(state, currentState);
-                                    }
-                                    return currentState;
-                                }
-                                else
-                                {
-                                    setAttributes(Collections.<String, Object>singletonMap(DESIRED_STATE,
-                                                                                           desiredState));
-
-                                    if (getState() == desiredState)
-                                    {
-                                        notifyStateChanged(state, desiredState);
-                                        return desiredState;
-                                    }
-                                    else
-                                    {
-                                        return getState();
-                                    }
-                                }
+                                notifyStateChanged(state, currentState);
                             }
-                        });
+
+                        }
+                    });
+                }
+                else
+                {
+                    ConfiguredObject<?> proxyForValidation =
+                            createProxyForValidation(Collections.<String, Object>singletonMap(
+                                    ConfiguredObject.DESIRED_STATE,
+                                    desiredState));
+                    Set<String> desiredStateOnlySet = Collections.unmodifiableSet(
+                            Collections.singleton(ConfiguredObject.DESIRED_STATE));
+                    authoriseSetAttributes(proxyForValidation, desiredStateOnlySet);
+                    validateChange(proxyForValidation, desiredStateOnlySet);
+
+                    if (changeAttribute(ConfiguredObject.DESIRED_STATE, currentDesiredState, desiredState))
+                    {
+                        attributeSet(ConfiguredObject.DESIRED_STATE,
+                                     currentDesiredState,
+                                     desiredState);
+
+                        return doAfter(attainStateIfOpenedOrReopenFailed(),new Runnable()
+                                       {
+                                           @Override
+                                           public void run()
+                                           {
+                                               if (getState() == desiredState)
+                                               {
+                                                   notifyStateChanged(state, desiredState);
+                                               }
+
+                                           }
+                                       }
+                            );
+                    }
+                    else
+                    {
+                        return Futures.immediateFuture(null);
+                    }
+                }
+
+            }
+        });
+
     }
 
     @Override
@@ -1429,20 +1708,62 @@
 
     public final void stop()
     {
-        setDesiredState(State.STOPPED);
+        doSync(setDesiredState(State.STOPPED));
     }
 
     public final void delete()
     {
-        if(getState() == State.UNINITIALIZED)
-        {
-            _desiredState = State.DELETED;
-        }
-        setDesiredState(State.DELETED);
-
+        doSync(deleteAsync());
     }
 
-    public final void start() { setDesiredState(State.ACTIVE); }
+    protected final <R>  R doSync(ListenableFuture<R> async)
+    {
+        try
+        {
+            return async.get();
+        }
+        catch (InterruptedException e)
+        {
+            throw new ServerScopedRuntimeException(e);
+        }
+        catch (ExecutionException e)
+        {
+            Throwable cause = e.getCause();
+            if(cause instanceof RuntimeException)
+            {
+                throw (RuntimeException) cause;
+            }
+            else if(cause instanceof Error)
+            {
+                throw (Error) cause;
+            }
+            else if(cause != null)
+            {
+                throw new ServerScopedRuntimeException(cause);
+            }
+            else
+            {
+                throw new ServerScopedRuntimeException(e);
+            }
+
+        }
+    }
+
+    public final ListenableFuture<Void> deleteAsync()
+    {
+        return setDesiredState(State.DELETED);
+    }
+
+    public final void start()
+    {
+        doSync(startAsync());
+    }
+
+    public ListenableFuture<Void> startAsync()
+    {
+        return setDesiredState(State.ACTIVE);
+    }
+
 
     protected void deleted()
     {
@@ -1527,24 +1848,175 @@
         _taskExecutor.run(task);
     }
 
+    @Override
+    public void setAttributes(Map<String, Object> attributes) throws IllegalStateException, AccessControlException, IllegalArgumentException
+    {
+        doSync(setAttributesAsync(attributes));
+    }
+
+    protected final ChainedListenableFuture doAfter(ListenableFuture<Void> first, final Runnable second)
+    {
+        return doAfter(getTaskExecutor().getExecutor(), first, second);
+    }
+
+    protected static final ChainedListenableFuture doAfter(Executor executor, ListenableFuture<Void> first, final Runnable second)
+    {
+        final ChainedSettableFuture returnVal = new ChainedSettableFuture(executor);
+        Futures.addCallback(first, new FutureCallback<Void>()
+        {
+            @Override
+            public void onSuccess(final Void result)
+            {
+                try
+                {
+                    second.run();
+                    returnVal.set(null);
+                }
+                catch(Throwable e)
+                {
+                    returnVal.setException(e);
+                }
+            }
+
+            @Override
+            public void onFailure(final Throwable t)
+            {
+                returnVal.setException(t);
+            }
+        }, executor);
+
+        return returnVal;
+    }
+
+    public static interface ChainedListenableFuture extends ListenableFuture<Void>
+    {
+        ChainedListenableFuture then(Runnable r);
+        ChainedListenableFuture then(Callable<ListenableFuture<Void>> r);
+    }
+
+    public static class ChainedSettableFuture extends AbstractFuture<Void> implements ChainedListenableFuture
+    {
+        private final Executor _exector;
+
+        public ChainedSettableFuture(final Executor executor)
+        {
+            _exector = executor;
+        }
+
+        @Override
+        public boolean set(Void value)
+        {
+            return super.set(value);
+        }
+
+        @Override
+        public boolean setException(Throwable throwable)
+        {
+            return super.setException(throwable);
+        }
+
+        @Override
+        public ChainedListenableFuture then(final Runnable r)
+        {
+            return doAfter(_exector, this, r);
+        }
+
+        @Override
+        public ChainedListenableFuture then(final Callable<ListenableFuture<Void>> r)
+        {
+            return doAfter(_exector, this,r);
+        }
+    }
+
+    protected final ChainedListenableFuture doAfter(ListenableFuture<Void> first, final Callable<ListenableFuture<Void>> second)
+    {
+        return doAfter(getTaskExecutor().getExecutor(), first, second);
+    }
+
+    protected static final ChainedListenableFuture doAfter(final Executor executor, ListenableFuture<Void> first, final Callable<ListenableFuture<Void>> second)
+    {
+        final ChainedSettableFuture returnVal = new ChainedSettableFuture(executor);
+        Futures.addCallback(first, new FutureCallback<Void>()
+        {
+            @Override
+            public void onSuccess(final Void result)
+            {
+                try
+                {
+                    final ListenableFuture<Void> future = second.call();
+                    Futures.addCallback(future, new FutureCallback<Void>()
+                    {
+                        @Override
+                        public void onSuccess(final Void result)
+                        {
+                            returnVal.set(null);
+                        }
+
+                        @Override
+                        public void onFailure(final Throwable t)
+                        {
+                            returnVal.setException(t);
+                        }
+                    }, executor);
+
+                }
+                catch(Throwable e)
+                {
+                    returnVal.setException(e);
+                }
+            }
+
+            @Override
+            public void onFailure(final Throwable t)
+            {
+                returnVal.setException(t);
+            }
+        }, executor);
+
+        return returnVal;
+    }
 
     @Override
-    public void setAttributes(final Map<String, Object> attributes) throws IllegalStateException, AccessControlException, IllegalArgumentException
+    public ListenableFuture<Void> setAttributesAsync(final Map<String, Object> attributes) throws IllegalStateException, AccessControlException, IllegalArgumentException
     {
+        final Map<String,Object> updateAttributes = new HashMap<>(attributes);
+        Object desiredState = updateAttributes.remove(ConfiguredObject.DESIRED_STATE);
         runTask(new VoidTask()
         {
             @Override
             public void execute()
             {
                 authoriseSetAttributes(createProxyForValidation(attributes), attributes.keySet());
-                changeAttributes(attributes);
+                validateChange(createProxyForValidation(attributes), attributes.keySet());
+
+                changeAttributes(updateAttributes);
             }
         });
+        if(desiredState != null)
+        {
+            State state;
+            if(desiredState instanceof State)
+            {
+                state = (State)desiredState;
+            }
+            else if(desiredState instanceof String)
+            {
+                state = State.valueOf((String)desiredState);
+            }
+            else
+            {
+                throw new IllegalArgumentException("Cannot convert an object of type " + desiredState.getClass().getName() + " to a State");
+            }
+            return setDesiredState(state);
+        }
+        else
+        {
+            return Futures.immediateFuture(null);
+        }
     }
 
     protected void changeAttributes(final Map<String, Object> attributes)
     {
-        validateChange(createProxyForValidation(attributes), attributes.keySet());
         Collection<String> names = getAttributeNames();
         for (String name : names)
         {
@@ -1938,6 +2410,74 @@
         }
     }
 
+    private static class CloseResult implements FutureResult
+    {
+        private volatile FutureResult _childFutureResult;
+
+        @Override
+        public boolean isComplete()
+        {
+            return _childFutureResult != null && _childFutureResult.isComplete();
+        }
+
+        @Override
+        public void waitForCompletion()
+        {
+            synchronized (this)
+            {
+                while (_childFutureResult == null)
+                {
+                    try
+                    {
+                        wait();
+                    }
+                    catch (InterruptedException e)
+                    {
+
+                    }
+                }
+            }
+            _childFutureResult.waitForCompletion();
+
+        }
+
+        @Override
+        public void waitForCompletion(final long timeout) throws TimeoutException
+        {
+            long startTime = System.currentTimeMillis();
+            long remaining = timeout;
+
+            synchronized (this)
+            {
+                while (_childFutureResult == null && remaining > 0)
+                {
+                    try
+                    {
+                        wait(remaining);
+                    }
+                    catch (InterruptedException e)
+                    {
+
+                    }
+                    remaining = startTime + timeout - System.currentTimeMillis();
+
+                    if(remaining <= 0)
+                    {
+                        throw new TimeoutException("Completion did not occur within given timeout: " + timeout);
+                    }
+                }
+            }
+            _childFutureResult.waitForCompletion(remaining);
+
+        }
+
+        public synchronized void setChildFutureResult(final FutureResult childFutureResult)
+        {
+            _childFutureResult = childFutureResult;
+            notifyAll();
+        }
+    }
+
 
     private static class AttributeGettingHandler implements InvocationHandler
     {
@@ -2127,7 +2667,8 @@
             {
                 if (source.getState() != State.DELETED)
                 {
-                    source.delete();
+                    // TODO - RG - This isn't right :-(
+                    source.deleteAsync();
                 }
             }
             finally
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObjectTypeFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObjectTypeFactory.java
index 5bf5e33..f97d2df 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObjectTypeFactory.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObjectTypeFactory.java
@@ -23,6 +23,10 @@
 import java.util.HashMap;
 import java.util.Map;
 
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
+import com.google.common.util.concurrent.SettableFuture;
+
 import org.apache.qpid.server.plugin.ConfiguredObjectTypeFactory;
 import org.apache.qpid.server.store.ConfiguredObjectDependency;
 import org.apache.qpid.server.store.ConfiguredObjectRecord;
@@ -59,6 +63,26 @@
         return instance;
     }
 
+
+    @Override
+    public ListenableFuture<X> createAsync(final ConfiguredObjectFactory factory,
+                    final Map<String, Object> attributes,
+                    final ConfiguredObject<?>... parents)
+    {
+        final SettableFuture<X> returnVal = SettableFuture.create();
+        final X instance = createInstance(attributes, parents);
+        final ListenableFuture<Void> createFuture = instance.createAsync();
+        createFuture.addListener(new Runnable()
+        {
+            @Override
+            public void run()
+            {
+                returnVal.set(instance);
+            }
+        }, MoreExecutors.sameThreadExecutor());
+        return returnVal;
+    }
+
     protected abstract X createInstance(Map<String, Object> attributes, ConfiguredObject<?>... parents);
 
     public final <C extends ConfiguredObject<?>> C getParent(Class<C> parentClass, ConfiguredObject<?>... parents)
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java
index b421c5a..c6ac7d4 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java
@@ -31,6 +31,9 @@
 import java.util.Map;
 import java.util.UUID;
 
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+
 import org.apache.qpid.common.QpidProperties;
 import org.apache.qpid.server.configuration.IllegalConfigurationException;
 import org.apache.qpid.server.configuration.store.ManagementModeStoreHandler;
@@ -194,11 +197,11 @@
     }
 
     @StateTransition(currentState = State.UNINITIALIZED, desiredState = State.ACTIVE)
-    protected void activate()
+    protected ListenableFuture<Void> activate()
     {
         final EventLogger eventLogger = _eventLogger;
 
-        EventLogger startupLogger;
+        final EventLogger startupLogger;
         if (isStartupLoggedToSystemOut())
         {
             //Create the composite (logging+SystemOut MessageLogger to be used during startup
@@ -232,17 +235,34 @@
         BrokerStoreUpgraderAndRecoverer upgrader = new BrokerStoreUpgraderAndRecoverer(this);
         upgrader.perform();
 
-        Broker broker = getBroker();
+        final Broker broker = getBroker();
 
         broker.setEventLogger(startupLogger);
-        broker.open();
+        final SettableFuture<Void> returnVal = SettableFuture.create();
+        broker.openAsync().addListener(
+                new Runnable()
+                {
+                    @Override
+                    public void run()
+                    {
+                        try
+                        {
 
-        if (broker.getState() == State.ACTIVE)
-        {
-            startupLogger.message(BrokerMessages.READY());
-            broker.setEventLogger(eventLogger);
-        }
+                            if (broker.getState() == State.ACTIVE)
+                            {
+                                startupLogger.message(BrokerMessages.READY());
+                                broker.setEventLogger(eventLogger);
+                            }
+                        }
+                        finally
+                        {
+                            returnVal.set(null);
+                        }
+                    }
+                }, getTaskExecutor().getExecutor()
+                                      );
 
+        return returnVal;
     }
 
     @Override
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Binding.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Binding.java
index 944ed97..c56698c 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Binding.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Binding.java
@@ -45,5 +45,4 @@
     @ManagedStatistic
     long getMatches();
 
-    void delete();
 }
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/Sender.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/CloseFuture.java
similarity index 81%
copy from qpid/java/common/src/main/java/org/apache/qpid/transport/Sender.java
copy to qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/CloseFuture.java
index 6519702..5e9d794 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/Sender.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/CloseFuture.java
@@ -1,5 +1,4 @@
 /*
- *
  * 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
@@ -16,24 +15,12 @@
  * KIND, either express or implied.  See the License for the
  * specific language governing permissions and limitations
  * under the License.
- *
- */
-package org.apache.qpid.transport;
-
-
-/**
- * Sender
- *
  */
 
-public interface Sender<T>
+package org.apache.qpid.server.model;
+
+
+public interface CloseFuture
 {
-    void setIdleTimeout(int i);
-
-    void send(T msg);
-
-    void flush();
-
-    void close();
-
+    public void runWhenComplete(final Runnable closeRunnable);
 }
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
index 2d60879..d2ab317 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
@@ -26,6 +26,8 @@
 import java.util.Set;
 import java.util.UUID;
 
+import com.google.common.util.concurrent.ListenableFuture;
+
 import org.apache.qpid.server.configuration.updater.TaskExecutor;
 import org.apache.qpid.server.store.ConfiguredObjectRecord;
 
@@ -236,6 +238,8 @@
                                                ConfiguredObject... otherParents);
 
     void setAttributes(Map<String, Object> attributes) throws IllegalStateException, AccessControlException, IllegalArgumentException;
+    ListenableFuture<Void> setAttributesAsync(Map<String, Object> attributes) throws IllegalStateException, AccessControlException, IllegalArgumentException;
+
 
     Class<? extends ConfiguredObject> getCategoryClass();
     Class<? extends ConfiguredObject> getTypeClass();
@@ -248,8 +252,12 @@
     ConfiguredObjectRecord asObjectRecord();
 
     void open();
+    ListenableFuture<Void> openAsync();
 
     void close();
+    ListenableFuture<Void> closeAsync();
+
+    ListenableFuture<Void> deleteAsync();
 
     TaskExecutor getTaskExecutor();
 
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFactory.java
index 7d40238..ed7c841 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFactory.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFactory.java
@@ -23,6 +23,8 @@
 import java.util.Collection;
 import java.util.Map;
 
+import com.google.common.util.concurrent.ListenableFuture;
+
 import org.apache.qpid.server.plugin.ConfiguredObjectTypeFactory;
 import org.apache.qpid.server.store.ConfiguredObjectRecord;
 import org.apache.qpid.server.store.UnresolvedConfiguredObject;
@@ -34,6 +36,8 @@
 
     <X extends ConfiguredObject<X>> X create(Class<X> clazz, Map<String, Object> attributes, ConfiguredObject<?>... parents);
 
+    <X extends ConfiguredObject<X>> ListenableFuture<X> createAsync(Class<X> clazz, Map<String, Object> attributes, ConfiguredObject<?>... parents);
+
 
 
     <X extends ConfiguredObject<X>> ConfiguredObjectTypeFactory<X> getConfiguredObjectTypeFactory(Class<X> categoryClass,
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFactoryImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFactoryImpl.java
index 5026df0..82da0fd 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFactoryImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFactoryImpl.java
@@ -26,6 +26,8 @@
 import java.util.HashMap;
 import java.util.Map;
 
+import com.google.common.util.concurrent.ListenableFuture;
+
 import org.apache.qpid.server.plugin.ConfiguredObjectTypeFactory;
 import org.apache.qpid.server.plugin.QpidServiceLoader;
 import org.apache.qpid.server.store.ConfiguredObjectRecord;
@@ -112,6 +114,18 @@
         return factory.create(this, attributes, parents);
     }
 
+
+    @Override
+    public <X extends ConfiguredObject<X>> ListenableFuture<X> createAsync(Class<X> clazz,
+                                                    final Map<String, Object> attributes,
+                                                    final ConfiguredObject<?>... parents)
+    {
+        ConfiguredObjectTypeFactory<X> factory = getConfiguredObjectTypeFactory(clazz, attributes);
+
+        return factory.createAsync(this, attributes, parents);
+    }
+
+
     @Override
     public <X extends ConfiguredObject<X>> ConfiguredObjectTypeFactory<X> getConfiguredObjectTypeFactory(final Class<X> categoryClass,
                                                                                                          Map<String, Object> attributes)
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java
index d0c6fb0..a93e6a6 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java
@@ -40,6 +40,7 @@
 import java.util.TreeMap;
 import java.util.TreeSet;
 
+import com.google.common.util.concurrent.ListenableFuture;
 import org.apache.log4j.Logger;
 
 import org.apache.qpid.server.plugin.ConfiguredObjectRegistration;
@@ -801,20 +802,37 @@
         {
             if(m.isAnnotationPresent(StateTransition.class))
             {
-                if(m.getParameterTypes().length == 0)
+                if(ListenableFuture.class.isAssignableFrom(m.getReturnType()))
                 {
-                    m.setAccessible(true);
-                    StateTransition annotation = m.getAnnotation(StateTransition.class);
-
-                    for(State state : annotation.currentState())
+                    if (m.getParameterTypes().length == 0)
                     {
-                        addStateTransition(state, annotation.desiredState(), m, map);
-                    }
+                        m.setAccessible(true);
+                        StateTransition annotation = m.getAnnotation(StateTransition.class);
 
+                        for (State state : annotation.currentState())
+                        {
+                            addStateTransition(state, annotation.desiredState(), m, map);
+                        }
+
+                    }
+                    else
+                    {
+                        throw new ServerScopedRuntimeException(
+                                "A state transition method must have no arguments. Method "
+                                + m.getName()
+                                + " on "
+                                + clazz.getName()
+                                + " does not meet this criteria.");
+                    }
                 }
                 else
                 {
-                    throw new ServerScopedRuntimeException("A state transition method must have no arguments. Method " + m.getName() + " on " + clazz.getName() + " does not meet this criteria.");
+                    throw new ServerScopedRuntimeException(
+                            "A state transition method must return a ListenableFuture. Method "
+                            + m.getName()
+                            + " on "
+                            + clazz.getName()
+                            + " does not meet this criteria.");
                 }
             }
         }
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Connection.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Connection.java
index b284414..1c24536 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Connection.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Connection.java
@@ -103,7 +103,6 @@
     //children
     Collection<Session> getSessions();
 
-    void delete();
 
 
 }
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java
index 7318a58..999a359 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java
@@ -23,6 +23,8 @@
 import java.util.Collection;
 import java.util.Set;
 
+import com.google.common.util.concurrent.ListenableFuture;
+
 @ManagedObject
 public interface Port<X extends Port<X>> extends ConfiguredObject<X>
 {
@@ -76,4 +78,6 @@
 
     void start();
 
+    ListenableFuture<Void> startAsync();
+
 }
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java
index cc758ba..c2338c0 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java
@@ -147,8 +147,6 @@
 
     void stop();
 
-    void delete();
-
     String getRedirectHost(AmqpPort<?> port);
 
     public static interface Transaction
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
index be1d6eb..036c4d7 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
@@ -35,6 +35,9 @@
 
 import javax.security.auth.Subject;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
 import org.apache.log4j.Logger;
 
 import org.apache.qpid.common.QpidProperties;
@@ -234,13 +237,40 @@
     }
 
     @StateTransition( currentState = State.UNINITIALIZED, desiredState = State.ACTIVE )
-    private void activate()
+    private ListenableFuture<Void> activate()
     {
         if(_parent.isManagementMode())
         {
-            _managementModeAuthenticationProvider.open();
-        }
+            final SettableFuture<Void> returnVal = SettableFuture.create();
 
+            _managementModeAuthenticationProvider.openAsync().addListener(
+                    new Runnable()
+                    {
+                        @Override
+                        public void run()
+                        {
+                            try
+                            {
+                                activateWithoutManagementMode();
+                            }
+                            finally
+                            {
+                                returnVal.set(null);
+                            }
+                        }
+                    }, getTaskExecutor().getExecutor()
+                                                                         );
+            return returnVal;
+        }
+        else
+        {
+            activateWithoutManagementMode();
+            return Futures.immediateFuture(null);
+        }
+    }
+
+    private void activateWithoutManagementMode()
+    {
         boolean hasBrokerAnyErroredChildren = false;
 
         for (final Class<? extends ConfiguredObject> childClass : getModel().getChildTypes(getCategoryClass()))
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java
index e039047..8bcbba9 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java
@@ -27,10 +27,13 @@
 import java.util.UUID;
 import java.util.concurrent.atomic.AtomicBoolean;
 
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
 import org.apache.log4j.Logger;
 
 import org.apache.qpid.protocol.AMQConstant;
 import org.apache.qpid.server.model.AbstractConfiguredObject;
+import org.apache.qpid.server.model.CloseFuture;
 import org.apache.qpid.server.model.ConfiguredObject;
 import org.apache.qpid.server.model.Connection;
 import org.apache.qpid.server.model.Port;
@@ -51,6 +54,7 @@
     private final Action _underlyingConnectionDeleteTask;
     private final AtomicBoolean _underlyingClosed = new AtomicBoolean(false);
     private AMQConnectionModel _underlyingConnection;
+    private final AtomicBoolean _closing = new AtomicBoolean();
 
     public ConnectionAdapter(final AMQConnectionModel conn)
     {
@@ -156,17 +160,59 @@
     }
 
     @StateTransition( currentState = State.ACTIVE, desiredState = State.DELETED)
-    private void doDelete()
+    private ListenableFuture<Void> doDelete()
     {
-        closeUnderlyingConnection();
-        deleted();
-        setState(State.DELETED);
+        final SettableFuture<Void> returnVal = SettableFuture.create();
+        asyncClose().addListener(
+                new Runnable()
+                {
+                    @Override
+                    public void run()
+                    {
+                        try
+                        {
+                            deleted();
+                            setState(State.DELETED);
+                        }
+                        finally
+                        {
+                            returnVal.set(null);
+                        }
+                    }
+                }, getTaskExecutor().getExecutor()
+                                );
+        return returnVal;
+    }
+
+    @Override
+    protected ListenableFuture<Void> beforeClose()
+    {
+        _closing.set(true);
+
+        return asyncClose();
+
+    }
+
+    private ListenableFuture<Void> asyncClose()
+    {
+        final SettableFuture<Void> closeFuture = SettableFuture.create();
+
+        _underlyingConnection.addDeleteTask(new Action()
+        {
+            @Override
+            public void performAction(final Object object)
+            {
+                closeFuture.set(null);
+            }
+        });
+
+        _underlyingConnection.closeAsync(AMQConstant.CONNECTION_FORCED, "Connection closed by external action");
+        return closeFuture;
     }
 
     @Override
     protected void onClose()
     {
-        closeUnderlyingConnection();
     }
 
     @Override
@@ -233,23 +279,54 @@
         // SessionAdapter installs delete task to cause session model object to delete
     }
 
-    private void closeUnderlyingConnection()
-    {
-        if (_underlyingClosed.compareAndSet(false, true))
-        {
-            _underlyingConnection.removeDeleteTask(_underlyingConnectionDeleteTask);
-            try
-            {
-                _underlyingConnection.close(AMQConstant.CONNECTION_FORCED, "Connection closed by external action");
-            }
-            catch (Exception e)
-            {
-                LOGGER.warn("Exception closing connection "
-                             + _underlyingConnection.getConnectionId()
-                             + " from "
-                             + _underlyingConnection.getRemoteAddressString(), e);
-            }
 
+    private static class ConnectionCloseFuture implements CloseFuture
+    {
+        private boolean _closed;
+
+        public synchronized void connectionClosed()
+        {
+            _closed = true;
+            notifyAll();
+
+        }
+
+        @Override
+        public void runWhenComplete(final Runnable closeRunnable)
+        {
+            if (_closed )
+            {
+                closeRunnable.run();
+            }
+            else
+            {
+                Thread t = new Thread(new Runnable()
+                {
+                    @Override
+                    public void run()
+                    {
+                        synchronized (ConnectionCloseFuture.this)
+                        {
+                            while (!_closed)
+                            {
+                                try
+                                {
+                                    ConnectionCloseFuture.this.wait();
+                                }
+                                catch (InterruptedException e)
+                                {
+                                }
+                            }
+
+                            closeRunnable.run();
+                        }
+                    }
+                });
+
+                t.setDaemon(true);
+                t.start();
+
+            }
         }
     }
 
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java
index fda8a6f..1a119be 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java
@@ -31,6 +31,9 @@
 import java.util.Set;
 import java.util.UUID;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
 import org.apache.log4j.Logger;
 
 import org.apache.qpid.server.configuration.BrokerProperties;
@@ -145,7 +148,8 @@
             GroupAdapter groupAdapter = new GroupAdapter(attrMap);
             principals.add(groupAdapter);
             groupAdapter.registerWithParents();
-            groupAdapter.open();
+            // TODO - we know this is safe, but the sync method shouldn't really be called from the management thread
+            groupAdapter.openAsync();
         }
 
     }
@@ -261,7 +265,7 @@
     }
 
     @StateTransition( currentState = { State.UNINITIALIZED, State.QUIESCED, State.ERRORED }, desiredState = State.ACTIVE )
-    private void activate()
+    private ListenableFuture<Void> activate()
     {
         if (_groupDatabase != null)
         {
@@ -278,29 +282,48 @@
                 throw new IllegalConfigurationException(String.format("Cannot load groups from '%s'", getPath()));
             }
         }
+        return Futures.immediateFuture(null);
     }
 
     @StateTransition( currentState = { State.QUIESCED, State.ACTIVE, State.ERRORED}, desiredState = State.DELETED )
-    private void doDelete()
+    private ListenableFuture<Void> doDelete()
     {
-        close();
-        File file = new File(getPath());
-        if (file.exists())
-        {
-            if (!file.delete())
-            {
-                throw new IllegalConfigurationException("Cannot delete group file");
-            }
-        }
+        final SettableFuture<Void> returnVal = SettableFuture.create();
+        closeAsync().addListener(
+                new Runnable()
+                {
+                    @Override
+                    public void run()
+                    {
+                        try
+                        {
+                            File file = new File(getPath());
+                            if (file.exists())
+                            {
+                                if (!file.delete())
+                                {
+                                    throw new IllegalConfigurationException("Cannot delete group file");
+                                }
+                            }
 
-        deleted();
-        setState(State.DELETED);
+                            deleted();
+                            setState(State.DELETED);
+                        }
+                        finally
+                        {
+                            returnVal.set(null);
+                        }
+                    }
+                }, getTaskExecutor().getExecutor()
+                           );
+        return returnVal;
     }
 
     @StateTransition( currentState = State.UNINITIALIZED, desiredState = State.QUIESCED)
-    private void startQuiesced()
+    private ListenableFuture<Void> startQuiesced()
     {
         setState(State.QUIESCED);
+        return Futures.immediateFuture(null);
     }
 
     public Set<Principal> getGroupPrincipalsForUser(String username)
@@ -352,9 +375,10 @@
         }
 
         @StateTransition( currentState = State.UNINITIALIZED, desiredState = State.ACTIVE )
-        private void activate()
+        private ListenableFuture<Void> activate()
         {
             setState(State.ACTIVE);
+            return Futures.immediateFuture(null);
         }
 
         @Override
@@ -371,7 +395,8 @@
                 attrMap.put(GroupMember.NAME, principal.getName());
                 GroupMemberAdapter groupMemberAdapter = new GroupMemberAdapter(attrMap);
                 groupMemberAdapter.registerWithParents();
-                groupMemberAdapter.open();
+                // todo - this will be safe, but the synchronous open should not be called from the management thread
+                groupMemberAdapter.openAsync();
                 members.add(groupMemberAdapter);
             }
             _groupPrincipal = new GroupPrincipal(getName());
@@ -432,11 +457,12 @@
         }
 
         @StateTransition( currentState = State.ACTIVE, desiredState = State.DELETED )
-        private void doDelete()
+        private ListenableFuture<Void> doDelete()
         {
             _groupDatabase.removeGroup(getName());
             deleted();
             setState(State.DELETED);
+            return Futures.immediateFuture(null);
         }
 
         @Override
@@ -494,17 +520,19 @@
             }
 
             @StateTransition(currentState = State.UNINITIALIZED, desiredState = State.ACTIVE)
-            private void activate()
+            private ListenableFuture<Void> activate()
             {
                 setState(State.ACTIVE);
+                return Futures.immediateFuture(null);
             }
 
             @StateTransition(currentState = State.ACTIVE, desiredState = State.DELETED)
-            private void doDelete()
+            private ListenableFuture<Void> doDelete()
             {
                 _groupDatabase.removeUserFromGroup(getName(), GroupAdapter.this.getName());
                 deleted();
                 setState(State.DELETED);
+                return Futures.immediateFuture(null);
             }
 
             @Override
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderImpl.java
index 2b77b0d..500df8c 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderImpl.java
@@ -37,16 +37,17 @@
 import java.util.Set;
 import java.util.TreeMap;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
 import org.apache.log4j.Logger;
-import org.apache.qpid.server.configuration.BrokerProperties;
-import org.apache.qpid.server.util.BaseAction;
-import org.apache.qpid.server.util.FileHelper;
 import org.codehaus.jackson.JsonParser;
 import org.codehaus.jackson.JsonProcessingException;
 import org.codehaus.jackson.map.ObjectMapper;
 import org.codehaus.jackson.map.SerializationConfig;
 import org.codehaus.jackson.type.TypeReference;
 
+import org.apache.qpid.server.configuration.BrokerProperties;
 import org.apache.qpid.server.configuration.IllegalConfigurationException;
 import org.apache.qpid.server.model.AbstractConfiguredObject;
 import org.apache.qpid.server.model.AuthenticationProvider;
@@ -55,6 +56,8 @@
 import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
 import org.apache.qpid.server.model.State;
 import org.apache.qpid.server.model.StateTransition;
+import org.apache.qpid.server.util.BaseAction;
+import org.apache.qpid.server.util.FileHelper;
 
 
 public class FileSystemPreferencesProviderImpl
@@ -128,7 +131,7 @@
     }
 
     @StateTransition( currentState = {State.UNINITIALIZED, State.ERRORED}, desiredState = State.ACTIVE )
-    private void activate()
+    private ListenableFuture<Void> activate()
     {
         if (_store != null)
         {
@@ -138,6 +141,7 @@
         {
             throw new IllegalStateException("Cannot open preferences provider " + getName() + " in state " + getState() );
         }
+        return Futures.immediateFuture(null);
     }
 
     @Override
@@ -171,33 +175,52 @@
     }
 
     @StateTransition(currentState = { State.ACTIVE }, desiredState = State.QUIESCED)
-    private void doQuiesce()
+    private ListenableFuture<Void> doQuiesce()
     {
         if(_store != null)
         {
             _store.close();
         }
         setState(State.QUIESCED);
+        return Futures.immediateFuture(null);
     }
 
     @StateTransition(currentState = { State.ACTIVE, State.QUIESCED, State.ERRORED }, desiredState = State.DELETED )
-    private void doDelete()
+    private ListenableFuture<Void> doDelete()
     {
-        close();
+        final SettableFuture<Void> returnVal = SettableFuture.create();
+        closeAsync().addListener(
+                new Runnable()
+                {
+                    @Override
+                    public void run()
+                    {
+                        try
+                        {
+                            if(_store != null)
+                            {
+                                _store.close();
+                                _store.delete();
+                                deleted();
+                                _authenticationProvider.setPreferencesProvider(null);
 
-        if(_store != null)
-        {
-            _store.close();
-            _store.delete();
-            deleted();
-            _authenticationProvider.setPreferencesProvider(null);
+                            }
+                            setState(State.DELETED);
+                        }
+                        finally
+                        {
+                            returnVal.set(null);
+                        }
+                    }
+                }, getTaskExecutor().getExecutor()
+                           );
 
-        }
-        setState(State.DELETED);
+        return returnVal;
+
     }
 
     @StateTransition(currentState = State.QUIESCED, desiredState = State.ACTIVE )
-    private void restart()
+    private ListenableFuture<Void> restart()
     {
         if (_store == null)
         {
@@ -206,6 +229,7 @@
 
         _store.open();
         setState(State.ACTIVE);
+        return Futures.immediateFuture(null);
     }
 
     @Override
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.java
index 7c9b439..cb412e8 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.java
@@ -26,6 +26,9 @@
 import java.util.Map;
 import java.util.UUID;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
 import org.apache.qpid.server.model.AbstractConfiguredObject;
 import org.apache.qpid.server.model.ConfiguredObject;
 import org.apache.qpid.server.model.Consumer;
@@ -169,10 +172,11 @@
     }
 
     @StateTransition(currentState = State.ACTIVE, desiredState = State.DELETED)
-    private void doDelete()
+    private ListenableFuture<Void> doDelete()
     {
         deleted();
         setState(State.DELETED);
+        return Futures.immediateFuture(null);
     }
 
 }
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java
index 791bbe4..0e6f18a 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java
@@ -27,6 +27,9 @@
 import java.util.Map;
 import java.util.Set;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
 import org.apache.log4j.Logger;
 
 import org.apache.qpid.server.configuration.IllegalConfigurationException;
@@ -226,14 +229,24 @@
     }
 
     @StateTransition(currentState = { State.ACTIVE, State.QUIESCED, State.ERRORED}, desiredState = State.DELETED )
-    private void doDelete()
+    private ListenableFuture<Void> doDelete()
     {
-        close();
-        setState(State.DELETED);
+        final SettableFuture<Void> returnVal = SettableFuture.create();
+        closeAsync().addListener(new Runnable()
+        {
+            @Override
+            public void run()
+            {
+                setState(State.DELETED);
+                returnVal.set(null);
+
+            }
+        }, getTaskExecutor().getExecutor());
+        return returnVal;
     }
 
     @StateTransition( currentState = {State.UNINITIALIZED, State.QUIESCED, State.ERRORED}, desiredState = State.ACTIVE )
-    protected void activate()
+    protected ListenableFuture<Void> activate()
     {
         try
         {
@@ -244,12 +257,14 @@
             setState(State.ERRORED);
             throw new IllegalConfigurationException("Unable to active port '" + getName() + "'of type " + getType() + " on " + getPort(), e);
         }
+        return Futures.immediateFuture(null);
     }
 
     @StateTransition( currentState = State.UNINITIALIZED, desiredState = State.QUIESCED)
-    private void startQuiesced()
+    private ListenableFuture<Void> startQuiesced()
     {
         setState(State.QUIESCED);
+        return Futures.immediateFuture(null);
     }
 
 
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java
index 43cb5f0..350f137 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java
@@ -40,6 +40,8 @@
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.X509TrustManager;
 
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
 import org.codehaus.jackson.map.ObjectMapper;
 
 import org.apache.qpid.server.configuration.BrokerProperties;
@@ -118,6 +120,8 @@
 
     private final Broker<?> _broker;
     private AcceptingTransport _transport;
+    private final AtomicBoolean _closing = new AtomicBoolean();
+    private final SettableFuture _noConnectionsRemain = SettableFuture.create();
 
     @ManagedObjectFactoryConstructor
     public AmqpPortImpl(Map<String, Object> attributes, Broker<?> broker)
@@ -254,6 +258,19 @@
     }
 
     @Override
+    protected ListenableFuture<Void> beforeClose()
+    {
+        _closing.set(true);
+
+        if (_connectionCount.get() == 0)
+        {
+            _noConnectionsRemain.set(null);
+        }
+
+        return _noConnectionsRemain;
+    }
+
+    @Override
     protected void onClose()
     {
         if (_transport != null)
@@ -262,6 +279,8 @@
             {
                 _broker.getEventLogger().message(BrokerMessages.SHUTTING_DOWN(String.valueOf(transport), getPort()));
             }
+
+
             _transport.close();
         }
     }
@@ -500,6 +519,11 @@
            _connectionCountWarningGiven.compareAndSet(true,false);
         }
 
+        if (_closing.get() && _connectionCount.get() == 0)
+        {
+            _noConnectionsRemain.set(null);
+        }
+
         return openConnections;
     }
 
@@ -511,7 +535,7 @@
     @Override
     public boolean canAcceptNewConnection(final SocketAddress remoteSocketAddress)
     {
-        return _maxOpenConnections < 0 || _connectionCount.get() < _maxOpenConnections;
+        return !_closing.get() && ( _maxOpenConnections < 0 || _connectionCount.get() < _maxOpenConnections );
     }
 
     @Override
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/PortFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/PortFactory.java
index 870621f..5c3000d 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/PortFactory.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/PortFactory.java
@@ -23,6 +23,8 @@
 import java.util.Map;
 import java.util.Set;
 
+import com.google.common.util.concurrent.ListenableFuture;
+
 import org.apache.qpid.server.configuration.IllegalConfigurationException;
 import org.apache.qpid.server.model.Broker;
 import org.apache.qpid.server.model.ConfiguredObject;
@@ -108,6 +110,14 @@
     }
 
     @Override
+    public ListenableFuture<X> createAsync(final ConfiguredObjectFactory factory,
+                                           final Map<String, Object> attributes,
+                                           final ConfiguredObject<?>... parents)
+    {
+        return getPortFactory(factory, attributes, (Broker<?>)parents[0]).createAsync(factory, attributes,parents);
+    }
+
+    @Override
     public UnresolvedConfiguredObject<X> recover(final ConfiguredObjectFactory factory,
                                                  final ConfiguredObjectRecord record,
                                                  final ConfiguredObject<?>... parents)
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/ConfiguredObjectTypeFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/ConfiguredObjectTypeFactory.java
index 0d16b4f..cd01870 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/ConfiguredObjectTypeFactory.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/ConfiguredObjectTypeFactory.java
@@ -20,19 +20,23 @@
  */
 package org.apache.qpid.server.plugin;
 
+import java.util.Map;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
 import org.apache.qpid.server.model.ConfiguredObject;
 import org.apache.qpid.server.model.ConfiguredObjectFactory;
 import org.apache.qpid.server.store.ConfiguredObjectRecord;
 import org.apache.qpid.server.store.UnresolvedConfiguredObject;
 
-import java.util.Map;
-
 public interface ConfiguredObjectTypeFactory<X extends ConfiguredObject<X>> extends Pluggable
 {
     Class<? super X> getCategoryClass();
 
     X create(final ConfiguredObjectFactory factory, Map<String, Object> attributes, ConfiguredObject<?>... parents);
 
+    ListenableFuture<X> createAsync(final ConfiguredObjectFactory factory, Map<String, Object> attributes, ConfiguredObject<?>... parents);
+
     UnresolvedConfiguredObject<X> recover(final ConfiguredObjectFactory factory,
                                           ConfiguredObjectRecord record,
                                           ConfiguredObject<?>... parents);
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/ProtocolEngineCreator.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/ProtocolEngineCreator.java
index 6e1b652..6100a2e 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/ProtocolEngineCreator.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/ProtocolEngineCreator.java
@@ -19,7 +19,7 @@
  *
  */
 
-import org.apache.qpid.protocol.ServerProtocolEngine;
+import org.apache.qpid.server.protocol.ServerProtocolEngine;
 import org.apache.qpid.server.model.Broker;
 import org.apache.qpid.server.model.Protocol;
 import org.apache.qpid.server.model.Transport;
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java
index 26e8271..95b9bf8 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java
@@ -40,7 +40,7 @@
      * @param cause
      * @param message
      */
-    public void close(AMQConstant cause, String message);
+    public void closeAsync(AMQConstant cause, String message);
 
     public void block();
 
@@ -53,7 +53,7 @@
      * @param cause
      * @param message
      */
-    public void closeSession(S session, AMQConstant cause, String message);
+    public void closeSessionAsync(S session, AMQConstant cause, String message);
 
     public long getConnectionId();
 
@@ -107,4 +107,8 @@
 
     void removeSessionListener(SessionModelListener listener);
 
+    void notifyWork();
+
+    boolean isMessageAssignmentSuspended();
+
 }
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java
index f13af47..3731ae2 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java
@@ -113,4 +113,8 @@
      * @return the time of the last activity or 0 if not in a transaction
      */
     long getTransactionUpdateTime();
+
+    void transportStateChanged();
+
+    void processPending();
 }
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java
index 49c0812..2ccf595 100755
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java
@@ -24,40 +24,31 @@
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
 import java.nio.ByteBuffer;
-import java.security.Principal;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
 
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLPeerUnverifiedException;
 import javax.security.auth.Subject;
 
 import org.apache.log4j.Logger;
 
-import org.apache.qpid.protocol.ServerProtocolEngine;
 import org.apache.qpid.server.logging.messages.ConnectionMessages;
 import org.apache.qpid.server.model.Broker;
 import org.apache.qpid.server.model.Protocol;
 import org.apache.qpid.server.model.Transport;
 import org.apache.qpid.server.model.port.AmqpPort;
 import org.apache.qpid.server.plugin.ProtocolEngineCreator;
-import org.apache.qpid.transport.Sender;
+import org.apache.qpid.server.util.Action;
+import org.apache.qpid.transport.ByteBufferSender;
 import org.apache.qpid.transport.network.NetworkConnection;
-import org.apache.qpid.transport.network.security.SSLStatus;
-import org.apache.qpid.transport.network.security.ssl.SSLBufferingSender;
-import org.apache.qpid.transport.network.security.ssl.SSLReceiver;
-import org.apache.qpid.transport.network.security.ssl.SSLUtil;
 
 public class MultiVersionProtocolEngine implements ServerProtocolEngine
 {
     private static final Logger _logger = Logger.getLogger(MultiVersionProtocolEngine.class);
 
     private final long _id;
-    private final SSLContext _sslContext;
-    private final boolean _wantClientAuth;
-    private final boolean _needClientAuth;
     private final AmqpPort<?> _port;
-    private final Transport _transport;
+    private Transport _transport;
     private final ProtocolEngineCreator[] _creators;
     private final Runnable _onCloseTask;
 
@@ -65,15 +56,13 @@
     private String _fqdn;
     private final Broker<?> _broker;
     private NetworkConnection _network;
-    private Sender<ByteBuffer> _sender;
+    private ByteBufferSender _sender;
     private final Protocol _defaultSupportedReply;
 
     private volatile ServerProtocolEngine _delegate = new SelfDelegateProtocolEngine();
+    private final AtomicReference<Action<ServerProtocolEngine>> _workListener = new AtomicReference<>();
 
     public MultiVersionProtocolEngine(final Broker<?> broker,
-                                      SSLContext sslContext,
-                                      boolean wantClientAuth,
-                                      boolean needClientAuth,
                                       final Set<Protocol> supported,
                                       final Protocol defaultSupportedReply,
                                       AmqpPort<?> port,
@@ -92,15 +81,23 @@
         _broker = broker;
         _supported = supported;
         _defaultSupportedReply = defaultSupportedReply;
-        _sslContext = sslContext;
-        _wantClientAuth = wantClientAuth;
-        _needClientAuth = needClientAuth;
         _port = port;
         _transport = transport;
         _creators = creators;
         _onCloseTask = onCloseTask;
     }
 
+    @Override
+    public void setMessageAssignmentSuspended(final boolean value)
+    {
+        _delegate.setMessageAssignmentSuspended(value);
+    }
+
+    @Override
+    public boolean isMessageAssignmentSuspended()
+    {
+        return _delegate.isMessageAssignmentSuspended();
+    }
 
     public SocketAddress getRemoteAddress()
     {
@@ -147,6 +144,12 @@
         _delegate.readerIdle();
     }
 
+    @Override
+    public void encryptedTransport()
+    {
+        _delegate.encryptedTransport();
+    }
+
 
     public void received(ByteBuffer msg)
     {
@@ -169,9 +172,21 @@
         return _delegate.getSubject();
     }
 
+    @Override
+    public boolean isTransportBlockedForWriting()
+    {
+        return _delegate.isTransportBlockedForWriting();
+    }
+
+    @Override
+    public void setTransportBlockedForWriting(final boolean blocked)
+    {
+        _delegate.setTransportBlockedForWriting(blocked);
+    }
+
     private static final int MINIMUM_REQUIRED_HEADER_BYTES = 8;
 
-    public void setNetworkConnection(NetworkConnection network, Sender<ByteBuffer> sender)
+    public void setNetworkConnection(NetworkConnection network, ByteBufferSender sender)
     {
         _network = network;
         SocketAddress address = _network.getLocalAddress();
@@ -198,10 +213,82 @@
         return _delegate.getLastWriteTime();
     }
 
+    @Override
+    public void processPending()
+    {
+        _delegate.processPending();
+    }
 
+    @Override
+    public boolean hasWork()
+    {
+        return _delegate.hasWork();
+    }
+
+    @Override
+    public void notifyWork()
+    {
+        _delegate.notifyWork();
+    }
+
+    @Override
+    public void setWorkListener(final Action<ServerProtocolEngine> listener)
+    {
+        _workListener.set(listener);
+        _delegate.setWorkListener(listener);
+    }
+
+    @Override
+    public void clearWork()
+    {
+        _delegate.clearWork();
+    }
 
     private class ClosedDelegateProtocolEngine implements ServerProtocolEngine
     {
+
+        @Override
+        public void setMessageAssignmentSuspended(final boolean value)
+        {
+
+        }
+
+        @Override
+        public boolean isMessageAssignmentSuspended()
+        {
+            return false;
+        }
+
+        @Override
+        public void processPending()
+        {
+
+        }
+
+        @Override
+        public boolean hasWork()
+        {
+            return false;
+        }
+
+        @Override
+        public void notifyWork()
+        {
+
+        }
+
+        @Override
+        public void setWorkListener(final Action<ServerProtocolEngine> listener)
+        {
+
+        }
+
+        @Override
+        public void clearWork()
+        {
+
+        }
+
         public SocketAddress getRemoteAddress()
         {
             return _network.getRemoteAddress();
@@ -247,7 +334,13 @@
 
         }
 
-        public void setNetworkConnection(NetworkConnection network, Sender<ByteBuffer> sender)
+        @Override
+        public void encryptedTransport()
+        {
+
+        }
+
+        public void setNetworkConnection(NetworkConnection network, ByteBufferSender sender)
         {
 
         }
@@ -274,12 +367,24 @@
         {
             return new Subject();
         }
+
+        @Override
+        public boolean isTransportBlockedForWriting()
+        {
+            return false;
+        }
+
+        @Override
+        public void setTransportBlockedForWriting(final boolean blocked)
+        {
+        }
     }
 
     private class SelfDelegateProtocolEngine implements ServerProtocolEngine
     {
         private final ByteBuffer _header = ByteBuffer.allocate(MINIMUM_REQUIRED_HEADER_BYTES);
-        private long _lastReadTime;
+        private long _lastReadTime = System.currentTimeMillis();
+        private final AtomicBoolean _hasWork = new AtomicBoolean();
 
         public SocketAddress getRemoteAddress()
         {
@@ -301,6 +406,47 @@
             return 0;
         }
 
+        @Override
+        public void setMessageAssignmentSuspended(final boolean value)
+        {
+        }
+
+        @Override
+        public boolean isMessageAssignmentSuspended()
+        {
+            return false;
+        }
+
+        @Override
+        public void processPending()
+        {
+
+        }
+
+        @Override
+        public boolean hasWork()
+        {
+            return _hasWork.get();
+        }
+
+        @Override
+        public void notifyWork()
+        {
+            _hasWork.set(true);
+        }
+
+        @Override
+        public void setWorkListener(final Action<ServerProtocolEngine> listener)
+        {
+
+        }
+
+        @Override
+        public void clearWork()
+        {
+            _hasWork.set(false);
+        }
+
         public void received(ByteBuffer msg)
         {
             _lastReadTime = System.currentTimeMillis();
@@ -360,15 +506,6 @@
                     }
                 }
 
-
-                if(newDelegate == null && looksLikeSSL(headerBytes))
-                {
-                    if(_sslContext !=  null)
-                    {
-                        newDelegate = new SslDelegateProtocolEngine();
-                    }
-                }
-
                 // If no delegate is found then send back a supported protocol version id
                 if(newDelegate == null)
                 {
@@ -398,8 +535,13 @@
                 }
                 else
                 {
+                    boolean hasWork = _delegate.hasWork();
+                    if (hasWork)
+                    {
+                        newDelegate.notifyWork();
+                    }
                     _delegate = newDelegate;
-
+                    _delegate.setWorkListener(_workListener.get());
                     _header.flip();
                     _delegate.received(_header);
                     if(msg.hasRemaining())
@@ -423,6 +565,17 @@
             return _delegate.getSubject();
         }
 
+        @Override
+        public boolean isTransportBlockedForWriting()
+        {
+            return false;
+        }
+
+        @Override
+        public void setTransportBlockedForWriting(final boolean blocked)
+        {
+        }
+
         public void exception(Throwable t)
         {
             _logger.error("Error establishing session", t);
@@ -466,7 +619,16 @@
             _network.close();
         }
 
-        public void setNetworkConnection(NetworkConnection network, Sender<ByteBuffer> sender)
+        @Override
+        public void encryptedTransport()
+        {
+            if(_transport == Transport.TCP)
+            {
+                _transport = Transport.SSL;
+            }
+        }
+
+        public void setNetworkConnection(NetworkConnection network, ByteBufferSender sender)
         {
 
         }
@@ -484,251 +646,5 @@
         }
     }
 
-    private class SslDelegateProtocolEngine implements ServerProtocolEngine
-    {
-        private final MultiVersionProtocolEngine _decryptEngine;
-        private final SSLEngine _engine;
-        private final SSLReceiver _sslReceiver;
-        private final SSLBufferingSender _sslSender;
-        private long _lastReadTime;
 
-        private SslDelegateProtocolEngine()
-        {
-
-            _decryptEngine = new MultiVersionProtocolEngine(_broker, null, false, false, _supported,
-                                                            _defaultSupportedReply, _port, Transport.SSL, _id, _creators,
-                                                            null);
-
-            _engine = _sslContext.createSSLEngine();
-            _engine.setUseClientMode(false);
-            SSLUtil.removeSSLv3Support(_engine);
-            SSLUtil.updateEnabledCipherSuites(_engine, _port.getEnabledCipherSuites(), _port.getDisabledCipherSuites());
-
-            if(_needClientAuth)
-            {
-                _engine.setNeedClientAuth(true);
-            }
-            else if(_wantClientAuth)
-            {
-                _engine.setWantClientAuth(true);
-            }
-
-            SSLStatus sslStatus = new SSLStatus();
-            _sslReceiver = new SSLReceiver(_engine,_decryptEngine,sslStatus);
-            _sslSender = new SSLBufferingSender(_engine,_sender,sslStatus);
-            _decryptEngine.setNetworkConnection(new SSLNetworkConnection(_engine,_network, _sslSender), _sslSender);
-        }
-
-        @Override
-        public void received(ByteBuffer msg)
-        {
-            _lastReadTime = System.currentTimeMillis();
-            _sslReceiver.received(msg);
-            _sslSender.send();
-            _sslSender.flush();
-        }
-
-        @Override
-        public void setNetworkConnection(NetworkConnection network, Sender<ByteBuffer> sender)
-        {
-            //TODO - Implement
-        }
-
-        @Override
-        public SocketAddress getRemoteAddress()
-        {
-            return _decryptEngine.getRemoteAddress();
-        }
-
-        @Override
-        public SocketAddress getLocalAddress()
-        {
-            return _decryptEngine.getLocalAddress();
-        }
-
-        @Override
-        public long getWrittenBytes()
-        {
-            return _decryptEngine.getWrittenBytes();
-        }
-
-        @Override
-        public long getReadBytes()
-        {
-            return _decryptEngine.getReadBytes();
-        }
-
-        @Override
-        public void closed()
-        {
-            _decryptEngine.closed();
-        }
-
-        @Override
-        public void writerIdle()
-        {
-            _decryptEngine.writerIdle();
-        }
-
-        @Override
-        public void readerIdle()
-        {
-            _decryptEngine.readerIdle();
-        }
-
-        @Override
-        public void exception(Throwable t)
-        {
-            _decryptEngine.exception(t);
-        }
-
-        @Override
-        public long getConnectionId()
-        {
-            return _decryptEngine.getConnectionId();
-        }
-
-        @Override
-        public Subject getSubject()
-        {
-            return _decryptEngine.getSubject();
-        }
-
-        @Override
-        public long getLastReadTime()
-        {
-            return _lastReadTime;
-        }
-
-        @Override
-        public long getLastWriteTime()
-        {
-            return _decryptEngine.getLastWriteTime();
-        }
-    }
-
-    private boolean looksLikeSSL(byte[] headerBytes)
-    {
-        return looksLikeSSLv3ClientHello(headerBytes) || looksLikeSSLv2ClientHello(headerBytes);
-    }
-
-    private boolean looksLikeSSLv3ClientHello(byte[] headerBytes)
-    {
-        return headerBytes[0] == 22 && // SSL Handshake
-               (headerBytes[1] == 3 && // SSL 3.0 / TLS 1.x
-                (headerBytes[2] == 0 || // SSL 3.0
-                 headerBytes[2] == 1 || // TLS 1.0
-                 headerBytes[2] == 2 || // TLS 1.1
-                 headerBytes[2] == 3)) && // TLS1.2
-               (headerBytes[5] == 1); // client_hello
-    }
-
-    private boolean looksLikeSSLv2ClientHello(byte[] headerBytes)
-    {
-        return headerBytes[0] == -128 &&
-               headerBytes[3] == 3 && // SSL 3.0 / TLS 1.x
-                (headerBytes[4] == 0 || // SSL 3.0
-                 headerBytes[4] == 1 || // TLS 1.0
-                 headerBytes[4] == 2 || // TLS 1.1
-                 headerBytes[4] == 3);
-    }
-
-
-    private static class SSLNetworkConnection implements NetworkConnection
-    {
-        private final NetworkConnection _network;
-        private final SSLBufferingSender _sslSender;
-        private final SSLEngine _engine;
-        private Principal _principal;
-        private boolean _principalChecked;
-        private final Object _lock = new Object();
-
-        public SSLNetworkConnection(SSLEngine engine, NetworkConnection network,
-                                    SSLBufferingSender sslSender)
-        {
-            _engine = engine;
-            _network = network;
-            _sslSender = sslSender;
-
-        }
-
-        @Override
-        public Sender<ByteBuffer> getSender()
-        {
-            return _sslSender;
-        }
-
-        @Override
-        public void start()
-        {
-            _network.start();
-        }
-
-        @Override
-        public void close()
-        {
-            _sslSender.close();
-
-            _network.close();
-        }
-
-        @Override
-        public SocketAddress getRemoteAddress()
-        {
-            return _network.getRemoteAddress();
-        }
-
-        @Override
-        public SocketAddress getLocalAddress()
-        {
-            return _network.getLocalAddress();
-        }
-
-        @Override
-        public void setMaxWriteIdle(int sec)
-        {
-            _network.setMaxWriteIdle(sec);
-        }
-
-        @Override
-        public void setMaxReadIdle(int sec)
-        {
-            _network.setMaxReadIdle(sec);
-        }
-
-        @Override
-        public Principal getPeerPrincipal()
-        {
-            synchronized (_lock)
-            {
-                if(!_principalChecked)
-                {
-                    try
-                    {
-                        _principal =  _engine.getSession().getPeerPrincipal();
-                    }
-                    catch (SSLPeerUnverifiedException e)
-                    {
-                        _principal = null;
-                    }
-
-                    _principalChecked = true;
-                }
-
-                return _principal;
-            }
-        }
-
-        @Override
-        public int getMaxReadIdle()
-        {
-            return _network.getMaxReadIdle();
-        }
-
-        @Override
-        public int getMaxWriteIdle()
-        {
-            return _network.getMaxWriteIdle();
-        }
-    }
 }
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactory.java
index 5c704c5..a51717e 100755
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactory.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactory.java
@@ -27,10 +27,7 @@
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicLong;
 
-import javax.net.ssl.SSLContext;
-
 import org.apache.qpid.protocol.ProtocolEngineFactory;
-import org.apache.qpid.protocol.ServerProtocolEngine;
 import org.apache.qpid.server.logging.messages.PortMessages;
 import org.apache.qpid.server.logging.subjects.PortLogSubject;
 import org.apache.qpid.server.model.Broker;
@@ -48,9 +45,6 @@
     private final Broker<?> _broker;
     private final Set<Protocol> _supported;
     private final Protocol _defaultSupportedReply;
-    private final SSLContext _sslContext;
-    private final boolean _wantClientAuth;
-    private final boolean _needClientAuth;
     private final AmqpPort<?> _port;
     private final Transport _transport;
     private final ProtocolEngineCreator[] _creators;
@@ -58,9 +52,6 @@
             _connectionCountDecrementingTask = new ConnectionCountDecrementingTask();
 
     public MultiVersionProtocolEngineFactory(Broker<?> broker,
-                                             SSLContext sslContext,
-                                             boolean wantClientAuth,
-                                             boolean needClientAuth,
                                              final Set<Protocol> supportedVersions,
                                              final Protocol defaultSupportedReply,
                                              AmqpPort<?> port,
@@ -73,7 +64,6 @@
         }
 
         _broker = broker;
-        _sslContext = sslContext;
         _supported = supportedVersions;
         _defaultSupportedReply = defaultSupportedReply;
         final List<ProtocolEngineCreator> creators = new ArrayList<ProtocolEngineCreator>();
@@ -83,18 +73,16 @@
         }
         Collections.sort(creators, new ProtocolEngineCreatorComparator());
         _creators = creators.toArray(new ProtocolEngineCreator[creators.size()]);
-        _wantClientAuth = wantClientAuth;
-        _needClientAuth = needClientAuth;
         _port = port;
         _transport = transport;
     }
 
-    public ServerProtocolEngine newProtocolEngine(final SocketAddress remoteSocketAddress)
+    public MultiVersionProtocolEngine newProtocolEngine(final SocketAddress remoteSocketAddress)
     {
         if(_port.canAcceptNewConnection(remoteSocketAddress))
         {
             _port.incrementConnectionCount();
-            return new MultiVersionProtocolEngine(_broker, _sslContext, _wantClientAuth, _needClientAuth,
+            return new MultiVersionProtocolEngine(_broker,
                                                   _supported, _defaultSupportedReply, _port, _transport,
                                                   ID_GENERATOR.getAndIncrement(),
                                                   _creators, _connectionCountDecrementingTask);
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/protocol/ServerProtocolEngine.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/ServerProtocolEngine.java
similarity index 67%
rename from qpid/java/common/src/main/java/org/apache/qpid/protocol/ServerProtocolEngine.java
rename to qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/ServerProtocolEngine.java
index 5c6918e..eba1f78 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/protocol/ServerProtocolEngine.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/ServerProtocolEngine.java
@@ -18,10 +18,13 @@
  * under the License.
  *
  */
-package org.apache.qpid.protocol;
+package org.apache.qpid.server.protocol;
 
 import javax.security.auth.Subject;
 
+import org.apache.qpid.protocol.ProtocolEngine;
+import org.apache.qpid.server.util.Action;
+
 public interface ServerProtocolEngine extends ProtocolEngine
 {
     /**
@@ -30,4 +33,22 @@
     long getConnectionId();
 
     Subject getSubject();
+
+    boolean isTransportBlockedForWriting();
+
+    void setTransportBlockedForWriting(boolean blocked);
+
+    void setMessageAssignmentSuspended(boolean value);
+
+    boolean isMessageAssignmentSuspended();
+
+    void processPending();
+
+    boolean hasWork();
+
+    void clearWork();
+
+    void notifyWork();
+
+    void setWorkListener(Action<ServerProtocolEngine> listener);
 }
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java
index 04d5fef..2a51657 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java
@@ -43,11 +43,15 @@
 
 import javax.security.auth.Subject;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 import org.apache.log4j.Logger;
 
 import org.apache.qpid.pool.ReferenceCountingExecutorService;
 import org.apache.qpid.server.binding.BindingImpl;
 import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.configuration.updater.Task;
+import org.apache.qpid.server.configuration.updater.TaskWithException;
 import org.apache.qpid.server.connection.SessionPrincipal;
 import org.apache.qpid.server.consumer.ConsumerImpl;
 import org.apache.qpid.server.consumer.ConsumerTarget;
@@ -96,6 +100,7 @@
 import org.apache.qpid.server.util.ServerScopedRuntimeException;
 import org.apache.qpid.server.util.StateChangeListener;
 import org.apache.qpid.server.virtualhost.VirtualHostImpl;
+import org.apache.qpid.server.virtualhost.VirtualHostUnavailableException;
 import org.apache.qpid.transport.TransportException;
 
 public abstract class AbstractQueue<X extends AbstractQueue<X>>
@@ -642,16 +647,51 @@
 
 
     @Override
-    public synchronized QueueConsumerImpl addConsumer(final ConsumerTarget target,
-                                     FilterManager filters,
+    public QueueConsumerImpl addConsumer(final ConsumerTarget target,
+                                     final FilterManager filters,
                                      final Class<? extends ServerMessage> messageClass,
                                      final String consumerName,
-                                     EnumSet<ConsumerImpl.Option> optionSet)
+                                     final EnumSet<ConsumerImpl.Option> optionSet)
             throws ExistingExclusiveConsumer, ExistingConsumerPreventsExclusive,
                    ConsumerAccessRefused
     {
 
+        try
+        {
+            return getTaskExecutor().run(new TaskWithException<QueueConsumerImpl, Exception>()
+            {
 
+                @Override
+                public QueueConsumerImpl execute()
+                        throws Exception
+                {
+
+                    return addConsumerInternal(target, filters, messageClass, consumerName, optionSet);
+                }
+            });
+        }
+        catch (ExistingExclusiveConsumer | ConsumerAccessRefused |
+            ExistingConsumerPreventsExclusive | RuntimeException e)
+        {
+            throw e;
+        }
+        catch (Exception e)
+        {
+            // Should never happen
+            throw new ServerScopedRuntimeException(e);
+        }
+
+
+    }
+
+    private QueueConsumerImpl addConsumerInternal(final ConsumerTarget target,
+                                                  FilterManager filters,
+                                                  final Class<? extends ServerMessage> messageClass,
+                                                  final String consumerName,
+                                                  EnumSet<ConsumerImpl.Option> optionSet)
+            throws ExistingExclusiveConsumer, ConsumerAccessRefused,
+                   ExistingConsumerPreventsExclusive
+    {
         if (hasExclusiveConsumer())
         {
             throw new ExistingExclusiveConsumer();
@@ -763,7 +803,7 @@
         QueueConsumerImpl consumer = new QueueConsumerImpl(this,
                                                            target,
                                                            consumerName,
-                                                           filters, 
+                                                           filters,
                                                            messageClass,
                                                            optionSet);
 
@@ -812,19 +852,18 @@
         deliverAsync();
 
         return consumer;
-
     }
 
     @Override
-    protected void beforeClose()
+    protected ListenableFuture<Void> beforeClose()
     {
         _closing = true;
-        super.beforeClose();
+        return super.beforeClose();
     }
 
 
 
-    synchronized void unregisterConsumer(final QueueConsumerImpl consumer)
+    void unregisterConsumer(final QueueConsumerImpl consumer)
     {
         if (consumer == null)
         {
@@ -835,7 +874,7 @@
 
         if (removed)
         {
-            consumer.close();
+            consumer.closeAsync();
             // No longer can the queue have an exclusive consumer
             setExclusiveSubscriber(null);
 
@@ -1219,10 +1258,6 @@
                     else
                     {
                         deliverMessage(sub, entry, false);
-                        if(sub.acquires())
-                        {
-                            entry.unlockAcquisition();
-                        }
                     }
                 }
             }
@@ -1798,7 +1833,15 @@
 
             for (BindingImpl b : bindingCopy)
             {
-                b.delete();
+                // TODO - RG - Need to sort out bindings!
+                if(getTaskExecutor().isTaskExecutorThread())
+                {
+                    b.deleteAsync();
+                }
+                else
+                {
+                    b.delete();
+                }
             }
 
             QueueConsumerList.ConsumerNodeIterator consumerNodeIterator = _consumerList.iterator();
@@ -1851,7 +1894,7 @@
             }
 
             _deleteTaskList.clear();
-            close();
+            closeAsync();
             deleted();
             //Log Queue Deletion
             getEventLogger().message(_logSubject, QueueMessages.DELETED());
@@ -2050,10 +2093,6 @@
                         else
                         {
                             deliverMessage(sub, node, batch);
-                            if(sub.acquires())
-                            {
-                                node.unlockAcquisition();
-                            }
                         }
 
                     }
@@ -2221,7 +2260,8 @@
                             if (consumerDone)
                             {
                                 sub.flushBatched();
-                                if (lastLoop && getNextAvailableEntry(sub) == null)
+                                boolean noMore = getNextAvailableEntry(sub) == null;
+                                if (lastLoop && noMore)
                                 {
                                     sub.queueEmpty();
                                 }
@@ -2595,7 +2635,7 @@
     {
         if (_virtualHost.getState() != State.ACTIVE)
         {
-            throw new ConnectionScopedRuntimeException("Virtualhost state " + _virtualHost.getState() + " prevents the message from being sent");
+            throw new VirtualHostUnavailableException(this._virtualHost);
         }
 
         if(!message.isReferenced(this))
@@ -2660,7 +2700,7 @@
         return allowed;
     }
 
-    private synchronized void updateExclusivityPolicy(ExclusivityPolicy desiredPolicy)
+    private void updateExclusivityPolicy(ExclusivityPolicy desiredPolicy)
             throws ExistingConsumerPreventsExclusive
     {
         if(desiredPolicy == null)
@@ -2862,24 +2902,27 @@
     //=============
 
     @StateTransition(currentState = {State.UNINITIALIZED,State.ERRORED}, desiredState = State.ACTIVE)
-    private void activate()
+    private ListenableFuture<Void> activate()
     {
         setState(State.ACTIVE);
+        return Futures.immediateFuture(null);
     }
 
     @StateTransition(currentState = State.UNINITIALIZED, desiredState = State.DELETED)
-    private void doDeleteBeforeInitialize()
+    private ListenableFuture<Void> doDeleteBeforeInitialize()
     {
         preSetAlternateExchange();
         setState(State.DELETED);
+        return Futures.immediateFuture(null);
     }
 
     @StateTransition(currentState = State.ACTIVE, desiredState = State.DELETED)
-    private void doDelete()
+    private ListenableFuture<Void> doDelete()
     {
         _virtualHost.removeQueue(this);
         preSetAlternateExchange();
         setState(State.DELETED);
+        return Futures.immediateFuture(null);
     }
 
 
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumer.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumer.java
index a2c275e..c459737 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumer.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumer.java
@@ -52,5 +52,4 @@
 
     QueueContext getQueueContext();
 
-    ConsumerTarget getTarget();
 }
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumerImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumerImpl.java
index 12ab353..b409b63 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumerImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumerImpl.java
@@ -198,7 +198,7 @@
 
         if(newState == ConsumerTarget.State.CLOSED && oldState != newState && !_closed.get())
         {
-            close();
+            closeAsync();
         }
         final StateChangeListener<? super QueueConsumerImpl, State> stateListener = getStateListener();
         if(stateListener != null)
@@ -323,6 +323,7 @@
     public final void flush()
     {
         _queue.flushConsumer(this);
+        _target.processPending();
     }
 
     public boolean resend(final QueueEntry entry)
@@ -514,6 +515,7 @@
         return _selector;
     }
 
+
     @Override
     public String toLogString()
     {
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueFactory.java
index 19265ef..b9ff650 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueFactory.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueFactory.java
@@ -22,6 +22,8 @@
 
 import java.util.Map;
 
+import com.google.common.util.concurrent.ListenableFuture;
+
 import org.apache.qpid.server.model.ConfiguredObject;
 import org.apache.qpid.server.model.ConfiguredObjectFactory;
 import org.apache.qpid.server.model.Port;
@@ -49,6 +51,14 @@
     }
 
     @Override
+    public ListenableFuture<X> createAsync(final ConfiguredObjectFactory factory,
+                                           final Map<String, Object> attributes,
+                                           final ConfiguredObject<?>... parents)
+    {
+        return getQueueFactory(factory, attributes).createAsync(factory, attributes, parents);
+    }
+
+    @Override
     public UnresolvedConfiguredObject<X> recover(final ConfiguredObjectFactory factory,
                                                  final ConfiguredObjectRecord record,
                                                  final ConfiguredObject<?>... parents)
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/FileKeyStoreImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/FileKeyStoreImpl.java
index bf64818..aedfb36 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/FileKeyStoreImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/FileKeyStoreImpl.java
@@ -37,6 +37,9 @@
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.KeyManagerFactory;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
 import org.apache.qpid.server.configuration.IllegalConfigurationException;
 import org.apache.qpid.server.model.AbstractConfiguredObject;
 import org.apache.qpid.server.model.Broker;
@@ -96,7 +99,7 @@
     }
 
     @StateTransition(currentState = {State.ACTIVE, State.ERRORED}, desiredState = State.DELETED)
-    protected void doDelete()
+    protected ListenableFuture<Void> doDelete()
     {
         // verify that it is not in use
         String storeName = getName();
@@ -111,12 +114,14 @@
         }
         deleted();
         setState(State.DELETED);
+        return Futures.immediateFuture(null);
     }
 
     @StateTransition(currentState = {State.UNINITIALIZED, State.ERRORED}, desiredState = State.ACTIVE)
-    protected void doActivate()
+    protected ListenableFuture<Void> doActivate()
     {
         setState(State.ACTIVE);
+        return Futures.immediateFuture(null);
     }
 
     @Override
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/FileTrustStoreImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/FileTrustStoreImpl.java
index b53dcf9..ce5a394 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/FileTrustStoreImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/FileTrustStoreImpl.java
@@ -37,6 +37,9 @@
 import javax.net.ssl.TrustManagerFactory;
 import javax.net.ssl.X509TrustManager;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
 import org.apache.qpid.server.configuration.IllegalConfigurationException;
 import org.apache.qpid.server.model.AbstractConfiguredObject;
 import org.apache.qpid.server.model.AuthenticationProvider;
@@ -96,7 +99,7 @@
     }
 
     @StateTransition(currentState = {State.ACTIVE, State.ERRORED}, desiredState = State.DELETED)
-    protected void doDelete()
+    protected ListenableFuture<Void> doDelete()
     {
         // verify that it is not in use
         String storeName = getName();
@@ -137,12 +140,14 @@
         }
         deleted();
         setState(State.DELETED);
+        return Futures.immediateFuture(null);
     }
 
     @StateTransition(currentState = {State.UNINITIALIZED, State.ERRORED}, desiredState = State.ACTIVE)
-    protected void doActivate()
+    protected ListenableFuture<Void> doActivate()
     {
         setState(State.ACTIVE);
+        return Futures.immediateFuture(null);
     }
 
     @Override
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/NonJavaKeyStoreImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/NonJavaKeyStoreImpl.java
index 0c68cb4..ea6a039 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/NonJavaKeyStoreImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/NonJavaKeyStoreImpl.java
@@ -56,6 +56,8 @@
 import javax.net.ssl.KeyManagerFactory;
 import javax.xml.bind.DatatypeConverter;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 import org.apache.log4j.Logger;
 
 import org.apache.qpid.server.configuration.IllegalConfigurationException;
@@ -181,7 +183,7 @@
     }
 
     @StateTransition(currentState = {State.ACTIVE, State.ERRORED}, desiredState = State.DELETED)
-    protected void doDelete()
+    protected ListenableFuture<Void> doDelete()
     {
         // verify that it is not in use
         String storeName = getName();
@@ -199,12 +201,14 @@
         }
         deleted();
         setState(State.DELETED);
+        return Futures.immediateFuture(null);
     }
 
     @StateTransition(currentState = {State.UNINITIALIZED, State.ERRORED}, desiredState = State.ACTIVE)
-    protected void doActivate()
+    protected ListenableFuture<Void> doActivate()
     {
         setState(State.ACTIVE);
+        return Futures.immediateFuture(null);
     }
 
     @Override
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/NonJavaTrustStoreImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/NonJavaTrustStoreImpl.java
index bd46b76..c181897 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/NonJavaTrustStoreImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/NonJavaTrustStoreImpl.java
@@ -44,6 +44,8 @@
 import javax.net.ssl.TrustManagerFactory;
 import javax.security.auth.x500.X500Principal;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 import org.apache.log4j.Logger;
 
 import org.apache.qpid.server.configuration.IllegalConfigurationException;
@@ -169,7 +171,7 @@
     }
 
     @StateTransition(currentState = {State.ACTIVE, State.ERRORED}, desiredState = State.DELETED)
-    protected void doDelete()
+    protected ListenableFuture<Void> doDelete()
     {
         // verify that it is not in use
         String storeName = getName();
@@ -212,12 +214,14 @@
         }
         deleted();
         setState(State.DELETED);
+        return Futures.immediateFuture(null);
     }
 
     @StateTransition(currentState = {State.UNINITIALIZED, State.ERRORED}, desiredState = State.ACTIVE)
-    protected void doActivate()
+    protected ListenableFuture<Void> doActivate()
     {
         setState(State.ACTIVE);
+        return Futures.immediateFuture(null);
     }
 
     @Override
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/SecurityManager.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/SecurityManager.java
index e0eb083..3bd44a9 100755
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/SecurityManager.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/SecurityManager.java
@@ -32,6 +32,7 @@
 import java.security.Principal;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.EnumSet;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java
index 88a761f..255457a 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java
@@ -27,6 +27,9 @@
 import java.util.Map;
 import java.util.Set;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
 import org.apache.log4j.Logger;
 
 import org.apache.qpid.server.configuration.IllegalConfigurationException;
@@ -151,13 +154,14 @@
     }
 
     @StateTransition( currentState = State.UNINITIALIZED, desiredState = State.QUIESCED )
-    protected void startQuiesced()
+    protected ListenableFuture<Void> startQuiesced()
     {
         setState(State.QUIESCED);
+        return Futures.immediateFuture(null);
     }
 
     @StateTransition( currentState = { State.UNINITIALIZED, State.QUIESCED, State.QUIESCED }, desiredState = State.ACTIVE )
-    protected void activate()
+    protected ListenableFuture<Void> activate()
     {
         try
         {
@@ -175,11 +179,11 @@
                 throw e;
             }
         }
-
+        return Futures.immediateFuture(null);
     }
 
     @StateTransition( currentState = { State.ACTIVE, State.QUIESCED, State.ERRORED}, desiredState = State.DELETED)
-    protected void doDelete()
+    protected ListenableFuture<Void> doDelete()
     {
 
         String providerName = getName();
@@ -195,15 +199,50 @@
             }
         }
 
-        close();
-        if (_preferencesProvider != null)
+        final SettableFuture<Void> returnVal = SettableFuture.create();
+
+        final ListenableFuture<Void> future = closeAsync();
+        future.addListener(new Runnable()
         {
-            _preferencesProvider.delete();
-        }
-        deleted();
+            @Override
+            public void run()
+            {
+                if (_preferencesProvider != null)
+                {
+                    _preferencesProvider.deleteAsync().addListener(new Runnable()
+                    {
+                        @Override
+                        public void run()
+                        {
+                            try
+                            {
+                                deleted();
+                                setState(State.DELETED);
+                            }
+                            finally
+                            {
+                                returnVal.set(null);
+                            }
+                        }
+                    }, getTaskExecutor().getExecutor());
+                }
+                else
+                {
+                    try
+                    {
+                        deleted();
 
-        setState(State.DELETED);
+                        setState(State.DELETED);
+                    }
+                    finally
+                    {
+                        returnVal.set(null);
+                    }
+                }
+            }
+        }, getTaskExecutor().getExecutor());
 
+        return  returnVal;
     }
 
     @Override
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ConfigModelPasswordManagingAuthenticationProvider.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ConfigModelPasswordManagingAuthenticationProvider.java
index 7773d9e..50a2a36 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ConfigModelPasswordManagingAuthenticationProvider.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ConfigModelPasswordManagingAuthenticationProvider.java
@@ -92,22 +92,15 @@
     @Override
     public void deleteUser(final String user) throws AccountNotFoundException
     {
-        runTask(new VoidTaskWithException<AccountNotFoundException>()
+        final ManagedUser authUser = getUser(user);
+        if(authUser != null)
         {
-            @Override
-            public void execute() throws AccountNotFoundException
-            {
-                final ManagedUser authUser = getUser(user);
-                if(authUser != null)
-                {
-                    authUser.delete();
-                }
-                else
-                {
-                    throw new AccountNotFoundException("No such user: '" + user + "'");
-                }
-            }
-        });
+            authUser.delete();
+        }
+        else
+        {
+            throw new AccountNotFoundException("No such user: '" + user + "'");
+        }
     }
 
     @Override
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ManagedUser.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ManagedUser.java
index b317b93..db69445 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ManagedUser.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ManagedUser.java
@@ -27,6 +27,9 @@
 import java.util.Map;
 import java.util.Set;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
 import org.apache.qpid.server.configuration.updater.VoidTask;
 import org.apache.qpid.server.model.AbstractConfiguredObject;
 import org.apache.qpid.server.model.ConfiguredObject;
@@ -85,10 +88,11 @@
     }
 
     @StateTransition(currentState = {State.ACTIVE}, desiredState = State.DELETED)
-    private void doDelete()
+    private ListenableFuture<Void> doDelete()
     {
         _authenticationManager.getUserMap().remove(getName());
         deleted();
+        return Futures.immediateFuture(null);
     }
 
     @Override
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
index 0fb8938..0fcab33 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
@@ -40,6 +40,9 @@
 import javax.security.sasl.SaslException;
 import javax.security.sasl.SaslServer;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
 import org.apache.log4j.Logger;
 
 import org.apache.qpid.server.configuration.BrokerProperties;
@@ -119,16 +122,9 @@
         super.onOpen();
         _principalDatabase = createDatabase();
         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);
-        }
     }
 
+
     protected abstract PrincipalDatabase createDatabase();
 
 
@@ -217,9 +213,44 @@
         return _principalDatabase;
     }
 
+    @StateTransition(currentState = {State.UNINITIALIZED,State.ERRORED}, desiredState = State.ACTIVE)
+    public ListenableFuture<Void> activate()
+    {
+        final SettableFuture<Void> returnVal = SettableFuture.create();
+        final List<Principal> users = _principalDatabase == null ? Collections.<Principal>emptyList() : _principalDatabase.getUsers();
+        _userMap.clear();
+        if(!users.isEmpty())
+        {
+            for (final Principal user : users)
+            {
+                final PrincipalAdapter principalAdapter = new PrincipalAdapter(user);
+                principalAdapter.registerWithParents();
+                principalAdapter.openAsync().addListener(new Runnable()
+                {
+                    @Override
+                    public void run()
+                    {
+                        _userMap.put(user, principalAdapter);
+                        if (_userMap.size() == users.size())
+                        {
+                            setState(State.ACTIVE);
+                            returnVal.set(null);
+                        }
+                    }
+                }, getTaskExecutor().getExecutor());
 
-    @StateTransition( currentState = { State.ACTIVE, State.QUIESCED, State.ERRORED}, desiredState = State.DELETED)
-    public void doDelete()
+            }
+
+            return returnVal;
+        }
+        else
+        {
+            return Futures.immediateFuture(null);
+        }
+    }
+
+    @StateTransition( currentState = { State.ACTIVE, State.QUIESCED, State.ERRORED, State.UNINITIALIZED}, desiredState = State.DELETED)
+    public ListenableFuture<Void> doDelete()
     {
         File file = new File(_path);
         if (file.exists() && file.isFile())
@@ -228,6 +259,7 @@
         }
         deleted();
         setState(State.DELETED);
+        return Futures.immediateFuture(null);
     }
 
     @Override
@@ -479,13 +511,14 @@
         }
 
         @StateTransition(currentState = {State.UNINITIALIZED,State.ERRORED}, desiredState = State.ACTIVE)
-        private void activate()
+        private ListenableFuture<Void> activate()
         {
             setState(State.ACTIVE);
+            return Futures.immediateFuture(null);
         }
 
         @StateTransition(currentState = State.ACTIVE, desiredState = State.DELETED)
-        private void doDelete()
+        private ListenableFuture<Void> doDelete()
         {
             try
             {
@@ -503,7 +536,7 @@
             {
                 LOGGER.warn("Failed to delete user " + _user, e);
             }
-
+            return Futures.immediateFuture(null);
         }
 
         @Override
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/group/GroupImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/group/GroupImpl.java
index 98607d2..96d32f4 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/group/GroupImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/group/GroupImpl.java
@@ -22,6 +22,9 @@
 
 import java.util.Map;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
 import org.apache.qpid.server.model.AbstractConfiguredObject;
 import org.apache.qpid.server.model.ConfiguredObject;
 import org.apache.qpid.server.model.Group;
@@ -77,16 +80,18 @@
 
 
     @StateTransition( currentState = { State.UNINITIALIZED, State.QUIESCED, State.ERRORED }, desiredState = State.ACTIVE )
-    private void activate()
+    private ListenableFuture<Void> activate()
     {
         setState(State.ACTIVE);
+        return Futures.immediateFuture(null);
     }
 
 
     @StateTransition(currentState = {State.ACTIVE}, desiredState = State.DELETED)
-    private void doDelete()
+    private ListenableFuture<Void> doDelete()
     {
         deleted();
+        return Futures.immediateFuture(null);
     }
 
 }
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/group/GroupMemberImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/group/GroupMemberImpl.java
index ea17db6..a86d380 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/group/GroupMemberImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/group/GroupMemberImpl.java
@@ -23,6 +23,9 @@
 import java.security.Principal;
 import java.util.Map;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
 import org.apache.qpid.server.model.AbstractConfiguredObject;
 import org.apache.qpid.server.model.Group;
 import org.apache.qpid.server.model.GroupMember;
@@ -61,15 +64,17 @@
 
 
     @StateTransition( currentState = { State.UNINITIALIZED, State.QUIESCED, State.ERRORED }, desiredState = State.ACTIVE )
-    private void activate()
+    private ListenableFuture<Void> activate()
     {
         setState(State.ACTIVE);
+        return Futures.immediateFuture(null);
     }
 
 
     @StateTransition(currentState = {State.ACTIVE}, desiredState = State.DELETED)
-    private void doDelete()
+    private ListenableFuture<Void> doDelete()
     {
         deleted();
+        return Futures.immediateFuture(null);
     }
 }
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/group/GroupProviderImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/group/GroupProviderImpl.java
index ecc166f..7dc032c 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/group/GroupProviderImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/group/GroupProviderImpl.java
@@ -26,6 +26,9 @@
 import java.util.Map;
 import java.util.Set;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
 import org.apache.qpid.server.model.AbstractConfiguredObject;
 import org.apache.qpid.server.model.Broker;
 import org.apache.qpid.server.model.ConfiguredObject;
@@ -89,16 +92,18 @@
     }
 
     @StateTransition( currentState = { State.UNINITIALIZED, State.QUIESCED, State.ERRORED }, desiredState = State.ACTIVE )
-    private void activate()
+    private ListenableFuture<Void> activate()
     {
         setState(State.ACTIVE);
+        return Futures.immediateFuture(null);
     }
 
 
     @StateTransition(currentState = {State.ACTIVE}, desiredState = State.DELETED)
-    private void doDelete()
+    private ListenableFuture<Void> doDelete()
     {
         deleted();
+        return Futures.immediateFuture(null);
     }
 
 }
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java
index 4dfaa71..5868ae6 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java
@@ -45,6 +45,7 @@
 import org.apache.qpid.server.store.handler.DistributedTransactionHandler;
 import org.apache.qpid.server.store.handler.MessageHandler;
 import org.apache.qpid.server.store.handler.MessageInstanceHandler;
+import org.apache.qpid.server.util.FutureResult;
 
 public abstract class AbstractJDBCMessageStore implements MessageStore
 {
@@ -834,10 +835,10 @@
         }
     }
 
-    private StoreFuture commitTranAsync(ConnectionWrapper connWrapper) throws StoreException
+    private FutureResult commitTranAsync(ConnectionWrapper connWrapper) throws StoreException
     {
         commitTran(connWrapper);
-        return StoreFuture.IMMEDIATE_FUTURE;
+        return FutureResult.IMMEDIATE_FUTURE;
     }
 
     private void abortTran(ConnectionWrapper connWrapper) throws StoreException
@@ -1231,14 +1232,14 @@
         }
 
         @Override
-        public StoreFuture commitTranAsync()
+        public FutureResult commitTranAsync()
         {
             checkMessageStoreOpen();
             doPreCommitActions();
-            StoreFuture storeFuture = AbstractJDBCMessageStore.this.commitTranAsync(_connWrapper);
+            FutureResult futureResult = AbstractJDBCMessageStore.this.commitTranAsync(_connWrapper);
             storedSizeChange(_storeSizeIncrease);
             doPostCommitActions();
-            return storeFuture;
+            return futureResult;
         }
 
         private void doPreCommitActions()
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java
index efe040f..eb887b4 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java
@@ -35,6 +35,7 @@
 import org.apache.qpid.server.store.handler.DistributedTransactionHandler;
 import org.apache.qpid.server.store.handler.MessageHandler;
 import org.apache.qpid.server.store.handler.MessageInstanceHandler;
+import org.apache.qpid.server.util.FutureResult;
 
 /** A simple message store that stores the messages in a thread-safe structure in memory. */
 public class MemoryMessageStore implements MessageStore
@@ -58,9 +59,9 @@
         private Set<Xid> _localDistributedTransactionsRemoves = new HashSet<Xid>();
 
         @Override
-        public StoreFuture commitTranAsync()
+        public FutureResult commitTranAsync()
         {
-            return StoreFuture.IMMEDIATE_FUTURE;
+            return FutureResult.IMMEDIATE_FUTURE;
         }
 
         @Override
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/Transaction.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/Transaction.java
index 6f7afcc..007f3ab 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/Transaction.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/Transaction.java
@@ -21,6 +21,7 @@
 package org.apache.qpid.server.store;
 
 import org.apache.qpid.server.message.EnqueueableMessage;
+import org.apache.qpid.server.util.FutureResult;
 
 public interface Transaction
 {
@@ -53,7 +54,7 @@
      * Commits all operations performed within a given transactional context.
      *
      */
-    StoreFuture commitTranAsync();
+    FutureResult commitTranAsync();
 
     /**
      * Abandons all operations performed within a given transactional context.
@@ -72,4 +73,4 @@
 
     void recordXid(long format, byte[] globalId, byte[] branchId, Transaction.Record[] enqueues,
                    Transaction.Record[] dequeues);
-}
\ No newline at end of file
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingConnection.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingConnection.java
new file mode 100644
index 0000000..ae5816a
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingConnection.java
@@ -0,0 +1,642 @@
+/*
+*
+ * 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.transport;
+
+import java.io.IOException;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.SocketChannel;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Set;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLEngineResult;
+import javax.net.ssl.SSLPeerUnverifiedException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.qpid.server.protocol.ServerProtocolEngine;
+import org.apache.qpid.server.util.Action;
+import org.apache.qpid.transport.ByteBufferSender;
+import org.apache.qpid.transport.SenderException;
+import org.apache.qpid.transport.network.NetworkConnection;
+import org.apache.qpid.transport.network.Ticker;
+import org.apache.qpid.transport.network.TransportEncryption;
+import org.apache.qpid.transport.network.security.ssl.SSLUtil;
+import org.apache.qpid.util.SystemUtils;
+
+public class NonBlockingConnection implements NetworkConnection, ByteBufferSender
+{
+    private static final Logger LOGGER = LoggerFactory.getLogger(NonBlockingConnection.class);
+    private final SocketChannel _socketChannel;
+    private final long _timeout;
+    private final Ticker _ticker;
+    private final SelectorThread _selector;
+    private int _maxReadIdle;
+    private int _maxWriteIdle;
+    private Principal _principal;
+    private boolean _principalChecked;
+    private final Object _lock = new Object();
+
+    public static final int NUMBER_OF_BYTES_FOR_TLS_CHECK = 6;
+
+    private final ConcurrentLinkedQueue<ByteBuffer> _buffers = new ConcurrentLinkedQueue<>();
+    private final List<ByteBuffer> _encryptedOutput = new ArrayList<>();
+
+    private final String _remoteSocketAddress;
+    private final AtomicBoolean _closed = new AtomicBoolean(false);
+    private final ServerProtocolEngine _protocolEngine;
+    private final int _receiveBufSize;
+    private final Set<TransportEncryption> _encryptionSet;
+    private final SSLContext _sslContext;
+    private final Runnable _onTransportEncryptionAction;
+    private ByteBuffer _netInputBuffer;
+    private SSLEngine _sslEngine;
+
+    private ByteBuffer _currentBuffer;
+
+    private TransportEncryption _transportEncryption;
+    private SSLEngineResult _status;
+    private volatile boolean _fullyWritten = true;
+    private boolean _workDone;
+
+
+    public NonBlockingConnection(SocketChannel socketChannel,
+                                 ServerProtocolEngine delegate,
+                                 int sendBufferSize,
+                                 int receiveBufferSize,
+                                 long timeout,
+                                 Ticker ticker,
+                                 final Set<TransportEncryption> encryptionSet,
+                                 final SSLContext sslContext,
+                                 final boolean wantClientAuth,
+                                 final boolean needClientAuth,
+                                 final Collection<String> enabledCipherSuites,
+                                 final Collection<String> disabledCipherSuites,
+                                 final Runnable onTransportEncryptionAction,
+                                 final SelectorThread selectorThread)
+    {
+        _socketChannel = socketChannel;
+        _timeout = timeout;
+        _ticker = ticker;
+        _selector = selectorThread;
+
+        _protocolEngine = delegate;
+        _receiveBufSize = receiveBufferSize;
+        _encryptionSet = encryptionSet;
+        _sslContext = sslContext;
+        _onTransportEncryptionAction = onTransportEncryptionAction;
+
+        delegate.setWorkListener(new Action<ServerProtocolEngine>()
+                                {
+                                    @Override
+                                    public void performAction(final ServerProtocolEngine object)
+                                    {
+                                        _selector.wakeup();
+                                    }
+                                });
+
+        if(encryptionSet.size() == 1)
+        {
+            _transportEncryption = _encryptionSet.iterator().next();
+            if (_transportEncryption == TransportEncryption.TLS)
+            {
+                onTransportEncryptionAction.run();
+            }
+        }
+
+        if(encryptionSet.contains(TransportEncryption.TLS))
+        {
+            _sslEngine = _sslContext.createSSLEngine();
+            _sslEngine.setUseClientMode(false);
+            SSLUtil.removeSSLv3Support(_sslEngine);
+            SSLUtil.updateEnabledCipherSuites(_sslEngine, enabledCipherSuites, disabledCipherSuites);
+
+            if(needClientAuth)
+            {
+                _sslEngine.setNeedClientAuth(true);
+            }
+            else if(wantClientAuth)
+            {
+                _sslEngine.setWantClientAuth(true);
+            }
+            _netInputBuffer = ByteBuffer.allocate(Math.max(_sslEngine.getSession().getPacketBufferSize(), _receiveBufSize * 2));
+        }
+
+        try
+        {
+            _remoteSocketAddress = _socketChannel.getRemoteAddress().toString();
+            _socketChannel.configureBlocking(false);
+        }
+        catch (IOException e)
+        {
+            throw new SenderException("Unable to prepare the channel for non-blocking IO", e);
+        }
+
+
+    }
+
+
+    public Ticker getTicker()
+    {
+        return _ticker;
+    }
+
+    public SocketChannel getSocketChannel()
+    {
+        return _socketChannel;
+    }
+
+    public void start()
+    {
+    }
+
+    public ByteBufferSender getSender()
+    {
+        return this;
+    }
+
+    public void close()
+    {
+        LOGGER.debug("Closing " + _remoteSocketAddress);
+        if(_closed.compareAndSet(false,true))
+        {
+            _protocolEngine.notifyWork();
+            getSelector().wakeup();
+        }
+    }
+
+    public SocketAddress getRemoteAddress()
+    {
+        return _socketChannel.socket().getRemoteSocketAddress();
+    }
+
+    public SocketAddress getLocalAddress()
+    {
+        return _socketChannel.socket().getLocalSocketAddress();
+    }
+
+    public void setMaxWriteIdle(int sec)
+    {
+        _maxWriteIdle = sec;
+    }
+
+    public void setMaxReadIdle(int sec)
+    {
+        _maxReadIdle = sec;
+    }
+
+    @Override
+    public Principal getPeerPrincipal()
+    {
+        synchronized (_lock)
+        {
+            if(!_principalChecked)
+            {
+                if (_sslEngine != null)
+                {
+                    try
+                    {
+                        _principal = _sslEngine.getSession().getPeerPrincipal();
+                    }
+                    catch (SSLPeerUnverifiedException e)
+                    {
+                        return null;
+                    }
+                }
+
+                _principalChecked = true;
+            }
+
+            return _principal;
+        }
+    }
+
+    @Override
+    public int getMaxReadIdle()
+    {
+        return _maxReadIdle;
+    }
+
+    @Override
+    public int getMaxWriteIdle()
+    {
+        return _maxWriteIdle;
+    }
+
+    public boolean canRead()
+    {
+        return true;
+    }
+
+    public boolean waitingForWrite()
+    {
+        return !_fullyWritten;
+    }
+
+    public boolean isStateChanged()
+    {
+
+        return _protocolEngine.hasWork();
+    }
+
+    public boolean doWork()
+    {
+        _protocolEngine.clearWork();
+        final boolean closed = _closed.get();
+        if (!closed)
+        {
+            try
+            {
+                _workDone = false;
+
+                long currentTime = System.currentTimeMillis();
+                int tick = _ticker.getTimeToNextTick(currentTime);
+                if (tick <= 0)
+                {
+                    _ticker.tick(currentTime);
+                }
+
+                _protocolEngine.setMessageAssignmentSuspended(true);
+
+                _protocolEngine.processPending();
+
+                _protocolEngine.setTransportBlockedForWriting(!doWrite());
+                boolean dataRead = doRead();
+                _fullyWritten = doWrite();
+                _protocolEngine.setTransportBlockedForWriting(!_fullyWritten);
+
+                if(dataRead || (_workDone && _netInputBuffer != null && _netInputBuffer.position() != 0))
+                {
+                    _protocolEngine.notifyWork();
+                }
+
+                // tell all consumer targets that it is okay to accept more
+                _protocolEngine.setMessageAssignmentSuspended(false);
+            }
+            catch (IOException e)
+            {
+                LOGGER.info("Exception performing I/O for thread '" + _remoteSocketAddress + "': " + e);
+                LOGGER.debug("Closing " + _remoteSocketAddress);
+                if(_closed.compareAndSet(false,true))
+                {
+                    _protocolEngine.notifyWork();
+                }
+            }
+        }
+        else
+        {
+
+            if(!SystemUtils.isWindows())
+            {
+                try
+                {
+                    _socketChannel.shutdownInput();
+                }
+                catch (IOException e)
+                {
+                    LOGGER.info("Exception shutting down input for thread '" + _remoteSocketAddress + "': " + e);
+
+                }
+            }
+            try
+            {
+                while(!doWrite())
+                {
+                }
+            }
+            catch (IOException e)
+            {
+                LOGGER.info("Exception performing final write/close for thread '" + _remoteSocketAddress + "': " + e);
+
+            }
+            LOGGER.debug("Closing receiver");
+            _protocolEngine.closed();
+
+            try
+            {
+                if(!SystemUtils.isWindows())
+                {
+                    _socketChannel.shutdownOutput();
+                }
+
+                _socketChannel.close();
+            }
+            catch (IOException e)
+            {
+                LOGGER.info("Exception closing socket thread '" + _remoteSocketAddress + "': " + e);
+            }
+        }
+
+        return closed;
+
+    }
+
+    public SelectorThread getSelector()
+    {
+        return _selector;
+    }
+
+    public boolean looksLikeSSLv2ClientHello(final byte[] headerBytes)
+    {
+        return headerBytes[0] == -128 &&
+               headerBytes[3] == 3 && // SSL 3.0 / TLS 1.x
+               (headerBytes[4] == 0 || // SSL 3.0
+                headerBytes[4] == 1 || // TLS 1.0
+                headerBytes[4] == 2 || // TLS 1.1
+                headerBytes[4] == 3);
+    }
+
+    public boolean doRead() throws IOException
+    {
+        boolean readData = false;
+        if(_transportEncryption == TransportEncryption.NONE)
+        {
+            int remaining = 0;
+            while (remaining == 0 && !_closed.get())
+            {
+                if (_currentBuffer == null || _currentBuffer.remaining() == 0)
+                {
+                    _currentBuffer = ByteBuffer.allocate(_receiveBufSize);
+                }
+                int read = _socketChannel.read(_currentBuffer);
+                if(read > 0)
+                {
+                    readData = true;
+                }
+                if (read == -1)
+                {
+                    _closed.set(true);
+                }
+                remaining = _currentBuffer.remaining();
+                if (LOGGER.isDebugEnabled())
+                {
+                    LOGGER.debug("Read " + read + " byte(s)");
+                }
+                ByteBuffer dup = _currentBuffer.duplicate();
+                dup.flip();
+                _currentBuffer = _currentBuffer.slice();
+                _protocolEngine.received(dup);
+            }
+        }
+        else if(_transportEncryption == TransportEncryption.TLS)
+        {
+            int read = 1;
+            while(!_closed.get() && read > 0  && _sslEngine.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.NEED_WRAP && (_status == null || _status.getStatus() != SSLEngineResult.Status.CLOSED))
+            {
+                read = _socketChannel.read(_netInputBuffer);
+                if (read == -1)
+                {
+                    _closed.set(true);
+                }
+                else if(read > 0)
+                {
+                    readData = true;
+                }
+                if (LOGGER.isDebugEnabled())
+                {
+                    LOGGER.debug("Read " + read + " encrypted bytes ");
+                }
+
+                _netInputBuffer.flip();
+
+
+                int unwrapped = 0;
+                boolean tasksRun;
+                do
+                {
+                    ByteBuffer appInputBuffer =
+                            ByteBuffer.allocate(_sslEngine.getSession().getApplicationBufferSize() + 50);
+
+                    _status = _sslEngine.unwrap(_netInputBuffer, appInputBuffer);
+                    tasksRun = runSSLEngineTasks(_status);
+
+                    appInputBuffer.flip();
+                    unwrapped = appInputBuffer.remaining();
+                    if(unwrapped > 0)
+                    {
+                        readData = true;
+                    }
+                    _protocolEngine.received(appInputBuffer);
+                }
+                while(unwrapped > 0 || tasksRun);
+
+                _netInputBuffer.compact();
+
+            }
+        }
+        else
+        {
+            int read = 1;
+            while (!_closed.get() && read > 0)
+            {
+
+                read = _socketChannel.read(_netInputBuffer);
+                if (read == -1)
+                {
+                    _closed.set(true);
+                }
+
+                if (LOGGER.isDebugEnabled())
+                {
+                    LOGGER.debug("Read " + read + " possibly encrypted bytes " + _netInputBuffer);
+                }
+
+                if (_netInputBuffer.position() >= NUMBER_OF_BYTES_FOR_TLS_CHECK)
+                {
+                    _netInputBuffer.flip();
+                    final byte[] headerBytes = new byte[NUMBER_OF_BYTES_FOR_TLS_CHECK];
+                    ByteBuffer dup = _netInputBuffer.duplicate();
+                    dup.get(headerBytes);
+
+                    _transportEncryption =  looksLikeSSL(headerBytes) ? TransportEncryption.TLS : TransportEncryption.NONE;
+                    LOGGER.debug("Identified transport encryption as " + _transportEncryption);
+
+                    if (_transportEncryption == TransportEncryption.NONE)
+                    {
+                        _protocolEngine.received(_netInputBuffer);
+                    }
+                    else
+                    {
+                        _onTransportEncryptionAction.run();
+                        _netInputBuffer.compact();
+                        readData = doRead();
+                    }
+                    break;
+                }
+            }
+        }
+        return readData;
+    }
+
+    public boolean doWrite() throws IOException
+    {
+
+        ByteBuffer[] bufArray = new ByteBuffer[_buffers.size()];
+        Iterator<ByteBuffer> bufferIterator = _buffers.iterator();
+        for (int i = 0; i < bufArray.length; i++)
+        {
+            bufArray[i] = bufferIterator.next();
+        }
+
+        int byteBuffersWritten = 0;
+
+        if(_transportEncryption == TransportEncryption.NONE)
+        {
+
+
+            long written = _socketChannel.write(bufArray);
+            if (LOGGER.isDebugEnabled())
+            {
+                LOGGER.debug("Written " + written + " bytes");
+            }
+
+            for (ByteBuffer buf : bufArray)
+            {
+                if (buf.remaining() == 0)
+                {
+                    byteBuffersWritten++;
+                    _buffers.poll();
+                }
+            }
+
+
+            return bufArray.length == byteBuffersWritten;
+        }
+        else if(_transportEncryption == TransportEncryption.TLS)
+        {
+            int remaining = 0;
+            do
+            {
+                if(_sslEngine.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.NEED_UNWRAP)
+                {
+                    _workDone = true;
+                    final ByteBuffer netBuffer = ByteBuffer.allocate(_sslEngine.getSession().getPacketBufferSize());
+                    _status = _sslEngine.wrap(bufArray, netBuffer);
+                    runSSLEngineTasks(_status);
+
+                    netBuffer.flip();
+                    remaining = netBuffer.remaining();
+                    if (remaining != 0)
+                    {
+                        _encryptedOutput.add(netBuffer);
+                    }
+                    for (ByteBuffer buf : bufArray)
+                    {
+                        if (buf.remaining() == 0)
+                        {
+                            byteBuffersWritten++;
+                            _buffers.poll();
+                        }
+                    }
+                }
+
+            }
+            while(remaining != 0 && _sslEngine.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.NEED_UNWRAP);
+            ByteBuffer[] encryptedBuffers = _encryptedOutput.toArray(new ByteBuffer[_encryptedOutput.size()]);
+            long written  = _socketChannel.write(encryptedBuffers);
+            if (LOGGER.isDebugEnabled())
+            {
+                LOGGER.debug("Written " + written + " encrypted bytes");
+            }
+            ListIterator<ByteBuffer> iter = _encryptedOutput.listIterator();
+            while(iter.hasNext())
+            {
+                ByteBuffer buf = iter.next();
+                if(buf.remaining() == 0)
+                {
+                    iter.remove();
+                }
+                else
+                {
+                    break;
+                }
+            }
+
+            return bufArray.length == byteBuffersWritten;
+
+        }
+        else
+        {
+            return true;
+        }
+    }
+
+    public boolean looksLikeSSLv3ClientHello(final byte[] headerBytes)
+    {
+        return headerBytes[0] == 22 && // SSL Handshake
+               (headerBytes[1] == 3 && // SSL 3.0 / TLS 1.x
+                (headerBytes[2] == 0 || // SSL 3.0
+                 headerBytes[2] == 1 || // TLS 1.0
+                 headerBytes[2] == 2 || // TLS 1.1
+                 headerBytes[2] == 3)) && // TLS1.2
+               (headerBytes[5] == 1); // client_hello
+    }
+
+    public boolean runSSLEngineTasks(final SSLEngineResult status)
+    {
+        if(status.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_TASK)
+        {
+            Runnable task;
+            while((task = _sslEngine.getDelegatedTask()) != null)
+            {
+                task.run();
+            }
+            return true;
+        }
+        return false;
+    }
+
+    public boolean looksLikeSSL(final byte[] headerBytes)
+    {
+        return looksLikeSSLv3ClientHello(headerBytes) || looksLikeSSLv2ClientHello(headerBytes);
+    }
+
+    @Override
+    public void send(final ByteBuffer msg)
+    {
+        assert Thread.currentThread().getName().startsWith(SelectorThread.IO_THREAD_NAME_PREFIX) : "Send called by unexpected thread " + Thread.currentThread().getName();
+
+        if (_closed.get())
+        {
+            LOGGER.warn("Send ignored as the connection is already closed");
+        }
+        else
+        {
+            _buffers.add(msg);
+            _protocolEngine.notifyWork();
+        }
+    }
+
+    @Override
+    public void flush()
+    {
+    }
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingNetworkTransport.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingNetworkTransport.java
new file mode 100644
index 0000000..7931371
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingNetworkTransport.java
@@ -0,0 +1,187 @@
+/*
+ *
+ * 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.transport;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.StandardSocketOptions;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.util.Set;
+
+import javax.net.ssl.SSLContext;
+
+import org.slf4j.LoggerFactory;
+
+import org.apache.qpid.configuration.CommonProperties;
+import org.apache.qpid.protocol.ProtocolEngineFactory;
+import org.apache.qpid.server.protocol.ServerProtocolEngine;
+import org.apache.qpid.transport.NetworkTransportConfiguration;
+import org.apache.qpid.transport.TransportException;
+import org.apache.qpid.transport.network.TransportEncryption;
+import org.apache.qpid.transport.network.io.AbstractNetworkTransport;
+import org.apache.qpid.transport.network.io.IdleTimeoutTicker;
+
+public class NonBlockingNetworkTransport
+{
+
+    private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(AbstractNetworkTransport.class);
+    private static final int TIMEOUT = Integer.getInteger(CommonProperties.IO_NETWORK_TRANSPORT_TIMEOUT_PROP_NAME,
+                                                          CommonProperties.IO_NETWORK_TRANSPORT_TIMEOUT_DEFAULT);
+    private static final int HANDSHAKE_TIMEOUT = Integer.getInteger(CommonProperties.HANDSHAKE_TIMEOUT_PROP_NAME ,
+                                                                   CommonProperties.HANDSHAKE_TIMEOUT_DEFAULT);
+    private SelectorThread _selector;
+
+
+    private  Set<TransportEncryption> _encryptionSet;
+    private volatile boolean _closed = false;
+    private NetworkTransportConfiguration _config;
+    private ProtocolEngineFactory _factory;
+    private SSLContext _sslContext;
+    private ServerSocketChannel _serverSocket;
+    private int _timeout;
+
+    public void close()
+    {
+        if(_selector != null)
+        {
+            try
+            {
+                if (_serverSocket != null)
+                {
+                    _selector.cancelAcceptingSocket(_serverSocket);
+                    _serverSocket.close();
+                }
+            }
+            catch (IOException e)
+            {
+                // TODO
+                e.printStackTrace();
+            }
+            finally
+            {
+
+                _selector.close();
+            }
+        }
+    }
+
+    public void accept(NetworkTransportConfiguration config,
+                       ProtocolEngineFactory factory,
+                       SSLContext sslContext,
+                       final Set<TransportEncryption> encryptionSet)
+    {
+        try
+        {
+
+            _config = config;
+            _factory = factory;
+            _sslContext = sslContext;
+            _timeout = TIMEOUT;
+
+            InetSocketAddress address = config.getAddress();
+
+            _serverSocket =  ServerSocketChannel.open();
+
+            _serverSocket.setOption(StandardSocketOptions.SO_REUSEADDR, true);
+            _serverSocket.bind(address);
+            _serverSocket.configureBlocking(false);
+            _encryptionSet = encryptionSet;
+
+            _selector = new SelectorThread(config.getAddress().toString(), this);
+            _selector.start();
+            _selector.addAcceptingSocket(_serverSocket);
+        }
+        catch (IOException e)
+        {
+            throw new TransportException("Failed to start AMQP on port : " + config, e);
+        }
+
+
+    }
+
+    public int getAcceptingPort()
+    {
+        return _serverSocket == null ? -1 : _serverSocket.socket().getLocalPort();
+    }
+
+    public void acceptSocketChannel(final SocketChannel socketChannel) throws IOException
+    {
+        final ServerProtocolEngine engine =
+                (ServerProtocolEngine) _factory.newProtocolEngine(socketChannel.socket()
+                                                                          .getRemoteSocketAddress());
+
+        if(engine != null)
+        {
+            socketChannel.setOption(StandardSocketOptions.TCP_NODELAY, _config.getTcpNoDelay());
+            socketChannel.socket().setSoTimeout(1000 * HANDSHAKE_TIMEOUT);
+
+            final Integer sendBufferSize = _config.getSendBufferSize();
+            final Integer receiveBufferSize = _config.getReceiveBufferSize();
+
+            socketChannel.setOption(StandardSocketOptions.SO_SNDBUF, sendBufferSize);
+            socketChannel.setOption(StandardSocketOptions.SO_RCVBUF, receiveBufferSize);
+
+
+            final IdleTimeoutTicker ticker = new IdleTimeoutTicker(engine, TIMEOUT);
+
+            NonBlockingConnection connection =
+                    new NonBlockingConnection(socketChannel,
+                                              engine,
+                                              sendBufferSize,
+                                              receiveBufferSize,
+                                              _timeout,
+                                              ticker,
+                                              _encryptionSet,
+                                              _sslContext,
+                                              _config.wantClientAuth(),
+                                              _config.needClientAuth(),
+                                              _config.getEnabledCipherSuites(),
+                                              _config.getDisabledCipherSuites(),
+                                              new Runnable()
+                                              {
+
+                                                  @Override
+                                                  public void run()
+                                                  {
+                                                      engine.encryptedTransport();
+                                                  }
+                                              },
+                                              _selector);
+
+            engine.setNetworkConnection(connection, connection.getSender());
+            connection.setMaxReadIdle(HANDSHAKE_TIMEOUT);
+
+            ticker.setConnection(connection);
+
+            connection.start();
+
+            _selector.addConnection(connection);
+
+        }
+        else
+        {
+            socketChannel.close();
+        }
+    }
+
+
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/SelectorThread.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/SelectorThread.java
new file mode 100644
index 0000000..774888e
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/SelectorThread.java
@@ -0,0 +1,320 @@
+/*
+ * 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.transport;
+
+import java.io.IOException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Queue;
+import java.util.Set;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.slf4j.LoggerFactory;
+
+import org.apache.qpid.thread.LoggingUncaughtExceptionHandler;
+
+
+public class SelectorThread extends Thread
+{
+    private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(SelectorThread.class);
+
+    public static final String IO_THREAD_NAME_PREFIX  = "NCS-";
+    private final Queue<Runnable> _tasks = new ConcurrentLinkedQueue<>();
+    private final Queue<NonBlockingConnection> _unregisteredConnections = new ConcurrentLinkedQueue<>();
+    private final Set<NonBlockingConnection> _unscheduledConnections = new HashSet<>();
+    private final Selector _selector;
+    private final AtomicBoolean _closed = new AtomicBoolean();
+    private final NetworkConnectionScheduler _scheduler = new NetworkConnectionScheduler();
+    private final NonBlockingNetworkTransport _transport;
+
+    SelectorThread(final String name, final NonBlockingNetworkTransport nonBlockingNetworkTransport)
+    {
+        super("SelectorThread-"+name);
+        _transport = nonBlockingNetworkTransport;
+        try
+        {
+            _selector = Selector.open();
+        }
+        catch (IOException e)
+        {
+            e.printStackTrace();
+            throw new RuntimeException(e);
+        }
+    }
+
+    public void addAcceptingSocket(final ServerSocketChannel socketChannel)
+    {
+        _tasks.add(new Runnable()
+                    {
+                        @Override
+                        public void run()
+                        {
+
+                            try
+                            {
+                                socketChannel.register(_selector, SelectionKey.OP_ACCEPT);
+                            }
+                            catch (ClosedChannelException e)
+                            {
+                                // TODO
+                                e.printStackTrace();
+                            }
+                        }
+                    });
+        _selector.wakeup();
+    }
+
+    public void cancelAcceptingSocket(final ServerSocketChannel socketChannel)
+    {
+        _tasks.add(new Runnable()
+        {
+            @Override
+            public void run()
+            {
+                SelectionKey selectionKey = socketChannel.keyFor(_selector);
+                if(selectionKey != null)
+                {
+                    selectionKey.cancel();
+                }
+            }
+        });
+        _selector.wakeup();
+    }
+
+    @Override
+    public void run()
+    {
+
+        long nextTimeout = 0;
+
+        try
+        {
+            while (!_closed.get())
+            {
+
+                _selector.select(nextTimeout);
+
+                while(_tasks.peek() != null)
+                {
+                    Runnable task = _tasks.poll();
+                    task.run();
+                }
+
+                List<NonBlockingConnection> toBeScheduled = new ArrayList<>();
+
+
+                Set<SelectionKey> selectionKeys = _selector.selectedKeys();
+                for (SelectionKey key : selectionKeys)
+                {
+                    if(key.isAcceptable())
+                    {
+                        // todo - should we schedule this rather than running in this thread?
+                        SocketChannel acceptedChannel = ((ServerSocketChannel)key.channel()).accept();
+                        _transport.acceptSocketChannel(acceptedChannel);
+                    }
+                    else
+                    {
+                        NonBlockingConnection connection = (NonBlockingConnection) key.attachment();
+
+                        key.channel().register(_selector, 0);
+
+                        toBeScheduled.add(connection);
+                        _unscheduledConnections.remove(connection);
+                    }
+
+                }
+                selectionKeys.clear();
+
+                while (_unregisteredConnections.peek() != null)
+                {
+                    NonBlockingConnection unregisteredConnection = _unregisteredConnections.poll();
+                    _unscheduledConnections.add(unregisteredConnection);
+
+
+                    final int ops = (unregisteredConnection.canRead() ? SelectionKey.OP_READ : 0)
+                                    | (unregisteredConnection.waitingForWrite() ? SelectionKey.OP_WRITE : 0);
+                    unregisteredConnection.getSocketChannel().register(_selector, ops, unregisteredConnection);
+
+                }
+
+                long currentTime = System.currentTimeMillis();
+                Iterator<NonBlockingConnection> iterator = _unscheduledConnections.iterator();
+                nextTimeout = Integer.MAX_VALUE;
+                while (iterator.hasNext())
+                {
+                    NonBlockingConnection connection = iterator.next();
+
+                    int period = connection.getTicker().getTimeToNextTick(currentTime);
+
+                    if (period <= 0 || connection.isStateChanged())
+                    {
+                        toBeScheduled.add(connection);
+                        connection.getSocketChannel().register(_selector, 0).cancel();
+                        iterator.remove();
+                    }
+                    else
+                    {
+                        nextTimeout = Math.min(period, nextTimeout);
+                    }
+                }
+
+                for (NonBlockingConnection connection : toBeScheduled)
+                {
+                    _scheduler.schedule(connection);
+                }
+
+            }
+        }
+        catch (IOException e)
+        {
+            //TODO
+            e.printStackTrace();
+        }
+        finally
+        {
+            try
+            {
+                _selector.close();
+            }
+            catch (IOException e)
+            {
+                e.printStackTrace();
+            }
+        }
+
+
+
+
+    }
+
+    public void addConnection(final NonBlockingConnection connection)
+    {
+        _unregisteredConnections.add(connection);
+        _selector.wakeup();
+
+    }
+
+    public void wakeup()
+    {
+        _selector.wakeup();
+    }
+
+    public void close()
+    {
+        _closed.set(true);
+        _selector.wakeup();
+        _scheduler.close();
+    }
+
+    private class NetworkConnectionScheduler
+    {
+        private final ScheduledThreadPoolExecutor _executor;
+        private final AtomicInteger _running = new AtomicInteger();
+        private final int _poolSize;
+
+        private NetworkConnectionScheduler()
+        {
+            _poolSize = Runtime.getRuntime().availableProcessors();
+            _executor = new ScheduledThreadPoolExecutor(_poolSize);
+            _executor.prestartAllCoreThreads();
+        }
+
+        public void processConnection(final NonBlockingConnection connection)
+        {
+            try
+            {
+                _running.incrementAndGet();
+                boolean rerun;
+                do
+                {
+                    rerun = false;
+                    boolean closed = connection.doWork();
+
+                    if (!closed)
+                    {
+
+                        if (connection.isStateChanged())
+                        {
+                            if (_running.get() == _poolSize)
+                            {
+                                schedule(connection);
+                            }
+                            else
+                            {
+                                rerun = true;
+                            }
+                        }
+                        else
+                        {
+                            SelectorThread.this.addConnection(connection);
+                        }
+                    }
+
+                } while (rerun);
+            }
+            finally
+            {
+                _running.decrementAndGet();
+            }
+        }
+
+        public void schedule(final NonBlockingConnection connection)
+        {
+            _executor.submit(new Runnable()
+                            {
+                                @Override
+                                public void run()
+                                {
+                                    String currentName = Thread.currentThread().getName();
+                                    try
+                                    {
+                                        Thread.currentThread().setName(
+                                                IO_THREAD_NAME_PREFIX + connection.getRemoteAddress().toString());
+                                        processConnection(connection);
+                                    }
+                                    finally
+                                    {
+                                        Thread.currentThread().setName(currentName);
+                                    }
+                                }
+                            });
+        }
+
+        public void close()
+        {
+            _executor.shutdown();
+        }
+
+
+
+    }
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransport.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransport.java
index 8f7a267..7874437 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransport.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransport.java
@@ -23,6 +23,7 @@
 import static org.apache.qpid.transport.ConnectionSettings.WILDCARD_ADDRESS;
 
 import java.net.InetSocketAddress;
+import java.util.EnumSet;
 import java.util.Collection;
 import java.util.Set;
 
@@ -34,11 +35,11 @@
 import org.apache.qpid.server.model.port.AmqpPort;
 import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory;
 import org.apache.qpid.transport.NetworkTransportConfiguration;
-import org.apache.qpid.transport.network.IncomingNetworkTransport;
+import org.apache.qpid.transport.network.TransportEncryption;
 
 class TCPandSSLTransport implements AcceptingTransport
 {
-    private IncomingNetworkTransport _networkTransport;
+    private NonBlockingNetworkTransport _networkTransport;
     private Set<Transport> _transports;
     private SSLContext _sslContext;
     private InetSocketAddress _bindingSocketAddress;
@@ -62,7 +63,7 @@
     @Override
     public void start()
     {
-        String bindingAddress = ((AmqpPort<?>)_port).getBindingAddress();
+        String bindingAddress = _port.getBindingAddress();
         if (WILDCARD_ADDRESS.equals(bindingAddress))
         {
             bindingAddress = null;
@@ -78,17 +79,25 @@
         }
 
         final NetworkTransportConfiguration settings = new ServerNetworkTransportConfiguration();
-        _networkTransport = org.apache.qpid.transport.network.Transport.getIncomingTransportInstance();
+        _networkTransport = new NonBlockingNetworkTransport();
         final MultiVersionProtocolEngineFactory protocolEngineFactory =
                 new MultiVersionProtocolEngineFactory(
-                _port.getParent(Broker.class), _transports.contains(Transport.TCP) ? _sslContext : null,
-                settings.wantClientAuth(), settings.needClientAuth(),
+                _port.getParent(Broker.class),
                 _supported,
                 _defaultSupportedProtocolReply,
                 _port,
                 _transports.contains(Transport.TCP) ? Transport.TCP : Transport.SSL);
 
-        _networkTransport.accept(settings, protocolEngineFactory, _transports.contains(Transport.TCP) ? null : _sslContext);
+        EnumSet<TransportEncryption> encryptionSet = EnumSet.noneOf(TransportEncryption.class);
+        if(_transports.contains(Transport.TCP))
+        {
+            encryptionSet.add(TransportEncryption.NONE);
+        }
+        if(_transports.contains(Transport.SSL))
+        {
+            encryptionSet.add(TransportEncryption.TLS);
+        }
+        _networkTransport.accept(settings, protocolEngineFactory, _sslContext, encryptionSet);
     }
 
     public int getAcceptingPort()
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java
index 65064b0..809c234 100755
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java
@@ -30,7 +30,7 @@
 import org.apache.qpid.server.message.ServerMessage;
 import org.apache.qpid.server.queue.BaseQueue;
 import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.StoreFuture;
+import org.apache.qpid.server.util.FutureResult;
 import org.apache.qpid.server.store.Transaction;
 import org.apache.qpid.server.store.TransactionLogResource;
 
@@ -55,7 +55,7 @@
 
     public static interface FutureRecorder
     {
-        public void recordFuture(StoreFuture future, Action action);
+        public void recordFuture(FutureResult future, Action action);
 
     }
 
@@ -83,7 +83,7 @@
      */
     public void addPostTransactionAction(final Action immediateAction)
     {
-        addFuture(StoreFuture.IMMEDIATE_FUTURE, immediateAction);
+        addFuture(FutureResult.IMMEDIATE_FUTURE, immediateAction);
 
     }
 
@@ -92,7 +92,7 @@
         Transaction txn = null;
         try
         {
-            StoreFuture future;
+            FutureResult future;
             if(queue.getMessageDurability().persist(message.isPersistent()))
             {
                 if (_logger.isDebugEnabled())
@@ -108,7 +108,7 @@
             }
             else
             {
-                future = StoreFuture.IMMEDIATE_FUTURE;
+                future = FutureResult.IMMEDIATE_FUTURE;
             }
             addFuture(future, postTransactionAction);
             postTransactionAction = null;
@@ -120,7 +120,7 @@
 
     }
 
-    private void addFuture(final StoreFuture future, final Action action)
+    private void addFuture(final FutureResult future, final Action action)
     {
         if(action != null)
         {
@@ -135,7 +135,7 @@
         }
     }
 
-    private void addEnqueueFuture(final StoreFuture future, final Action action, boolean persistent)
+    private void addEnqueueFuture(final FutureResult future, final Action action, boolean persistent)
     {
         if(action != null)
         {
@@ -178,7 +178,7 @@
                 }
 
             }
-            StoreFuture future;
+            FutureResult future;
             if(txn != null)
             {
                 future = txn.commitTranAsync();
@@ -186,7 +186,7 @@
             }
             else
             {
-                future = StoreFuture.IMMEDIATE_FUTURE;
+                future = FutureResult.IMMEDIATE_FUTURE;
             }
             addFuture(future, postTransactionAction);
             postTransactionAction = null;
@@ -204,7 +204,7 @@
         Transaction txn = null;
         try
         {
-            StoreFuture future;
+            FutureResult future;
             if(queue.getMessageDurability().persist(message.isPersistent()))
             {
                 if (_logger.isDebugEnabled())
@@ -219,7 +219,7 @@
             }
             else
             {
-                future = StoreFuture.IMMEDIATE_FUTURE;
+                future = FutureResult.IMMEDIATE_FUTURE;
             }
             addEnqueueFuture(future, postTransactionAction, message.isPersistent());
             postTransactionAction = null;
@@ -255,7 +255,7 @@
                 }
             }
 
-            StoreFuture future;
+            FutureResult future;
             if (txn != null)
             {
                 future = txn.commitTranAsync();
@@ -263,7 +263,7 @@
             }
             else
             {
-                future = StoreFuture.IMMEDIATE_FUTURE;
+                future = FutureResult.IMMEDIATE_FUTURE;
             }
             addEnqueueFuture(future, postTransactionAction, message.isPersistent());
             postTransactionAction = null;
@@ -281,7 +281,7 @@
     {
         if(immediatePostTransactionAction != null)
         {
-            addFuture(StoreFuture.IMMEDIATE_FUTURE, new Action()
+            addFuture(FutureResult.IMMEDIATE_FUTURE, new Action()
             {
                 public void postCommit()
                 {
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java
index 349ec79..b800556 100755
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java
@@ -23,6 +23,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.concurrent.TimeoutException;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -32,7 +33,7 @@
 import org.apache.qpid.server.message.ServerMessage;
 import org.apache.qpid.server.queue.BaseQueue;
 import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.StoreFuture;
+import org.apache.qpid.server.util.FutureResult;
 import org.apache.qpid.server.store.Transaction;
 import org.apache.qpid.server.store.TransactionLogResource;
 
@@ -53,7 +54,7 @@
     private final MessageStore _transactionLog;
     private volatile long _txnStartTime = 0L;
     private volatile long _txnUpdateTime = 0l;
-    private StoreFuture _asyncTran;
+    private FutureResult _asyncTran;
 
     public LocalTransaction(MessageStore transactionLog)
     {
@@ -271,16 +272,16 @@
         }
     }
 
-    public StoreFuture commitAsync(final Runnable deferred)
+    public FutureResult commitAsync(final Runnable deferred)
     {
         sync();
-        StoreFuture future = StoreFuture.IMMEDIATE_FUTURE;
+        FutureResult future = FutureResult.IMMEDIATE_FUTURE;
         if(_transaction != null)
         {
-            future = new StoreFuture()
+            future = new FutureResult()
                         {
                             private volatile boolean _completed = false;
-                            private StoreFuture _underlying = _transaction.commitTranAsync();
+                            private FutureResult _underlying = _transaction.commitTranAsync();
 
                             @Override
                             public boolean isComplete()
@@ -298,6 +299,17 @@
                                 }
                             }
 
+                            @Override
+                            public void waitForCompletion(final long timeout) throws TimeoutException
+                            {
+
+                                if(!_completed)
+                                {
+                                    _underlying.waitForCompletion(timeout);
+                                    checkUnderlyingCompletion();
+                                }
+                            }
+
                             private synchronized boolean checkUnderlyingCompletion()
                             {
                                 if(!_completed && _underlying.isComplete())
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/StoreFuture.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/FutureResult.java
similarity index 73%
rename from qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/StoreFuture.java
rename to qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/FutureResult.java
index 7d3bf90..2aab308 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/StoreFuture.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/FutureResult.java
@@ -18,11 +18,13 @@
 * under the License.
 *
 */
-package org.apache.qpid.server.store;
+package org.apache.qpid.server.util;
 
-public interface StoreFuture
+import java.util.concurrent.TimeoutException;
+
+public interface FutureResult
 {
-    StoreFuture IMMEDIATE_FUTURE = new StoreFuture()
+    FutureResult IMMEDIATE_FUTURE = new FutureResult()
     {
         public boolean isComplete()
         {
@@ -32,9 +34,17 @@
         public void waitForCompletion()
         {
         }
+
+        @Override
+        public void waitForCompletion(final long timeout) throws TimeoutException
+        {
+
+        }
     };
 
     boolean isComplete();
 
     void waitForCompletion();
+
+    void waitForCompletion(long timeout) throws TimeoutException;
 }
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java
index 3680e47..220beb2 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java
@@ -37,10 +37,15 @@
 import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 
 import javax.security.auth.Subject;
 
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
 import org.apache.log4j.Logger;
 
 import org.apache.qpid.exchange.ExchangeDefaults;
@@ -61,6 +66,7 @@
 import org.apache.qpid.server.message.MessageSource;
 import org.apache.qpid.server.message.ServerMessage;
 import org.apache.qpid.server.model.*;
+import org.apache.qpid.server.model.Connection;
 import org.apache.qpid.server.model.adapter.ConnectionAdapter;
 import org.apache.qpid.server.model.port.AmqpPort;
 import org.apache.qpid.server.plugin.ConnectionValidator;
@@ -384,27 +390,65 @@
         return isStoreEmptyHandler.isEmpty();
     }
 
-    protected void createDefaultExchanges()
+    protected ListenableFuture<Void> createDefaultExchanges()
     {
-        Subject.doAs(getSecurityManager().getSubjectWithAddedSystemRights(), new PrivilegedAction<Void>()
+        return Subject.doAs(getSecurityManager().getSubjectWithAddedSystemRights(), new PrivilegedAction<ListenableFuture<Void>>()
         {
+            private static final int TOTAL_STANDARD_EXCHANGES = 4;
+            private final AtomicInteger _createdExchangeCount = new AtomicInteger();
+            private SettableFuture<Void> _future = SettableFuture.create();
+
             @Override
-            public Void run()
+            public ListenableFuture<Void> run()
             {
                 addStandardExchange(ExchangeDefaults.DIRECT_EXCHANGE_NAME, ExchangeDefaults.DIRECT_EXCHANGE_CLASS);
                 addStandardExchange(ExchangeDefaults.TOPIC_EXCHANGE_NAME, ExchangeDefaults.TOPIC_EXCHANGE_CLASS);
                 addStandardExchange(ExchangeDefaults.HEADERS_EXCHANGE_NAME, ExchangeDefaults.HEADERS_EXCHANGE_CLASS);
                 addStandardExchange(ExchangeDefaults.FANOUT_EXCHANGE_NAME, ExchangeDefaults.FANOUT_EXCHANGE_CLASS);
-                return null;
+                return _future;
             }
 
-            void addStandardExchange(String name, String type)
+            private void standardExchangeCreated()
             {
+                if(_createdExchangeCount.incrementAndGet() == TOTAL_STANDARD_EXCHANGES)
+                {
+                    _future.set(null);
+                }
+            }
+
+            ListenableFuture<Void> addStandardExchange(String name, String type)
+            {
+
                 Map<String, Object> attributes = new HashMap<String, Object>();
                 attributes.put(Exchange.NAME, name);
                 attributes.put(Exchange.TYPE, type);
                 attributes.put(Exchange.ID, UUIDGenerator.generateExchangeUUID(name, getName()));
-                childAdded(addExchange(attributes));
+                final ListenableFuture<ExchangeImpl> future = addExchangeAsync(attributes);
+                final SettableFuture<Void> returnVal = SettableFuture.create();
+                Futures.addCallback(future, new FutureCallback<ExchangeImpl>()
+                {
+                    @Override
+                    public void onSuccess(final ExchangeImpl result)
+                    {
+                        try
+                        {
+                            childAdded(result);
+                        }
+                        finally
+                        {
+                            standardExchangeCreated();
+                        }
+
+                    }
+
+                    @Override
+                    public void onFailure(final Throwable t)
+                    {
+                        standardExchangeCreated();
+                    }
+                }, getTaskExecutor().getExecutor());
+
+                return returnVal;
             }
         });
     }
@@ -747,6 +791,23 @@
 
     }
 
+    private ListenableFuture<ExchangeImpl> addExchangeAsync(Map<String,Object> attributes)
+            throws ExchangeExistsException, ReservedExchangeNameException,
+                   NoFactoryForTypeException
+    {
+        try
+        {
+            ListenableFuture result = getObjectFactory().createAsync(Exchange.class, attributes, this);
+            return result;
+        }
+        catch (DuplicateNameException e)
+        {
+            throw new ExchangeExistsException(getExchange(e.getName()));
+        }
+
+    }
+
+
     @Override
     public void removeExchange(ExchangeImpl exchange, boolean force)
             throws ExchangeIsAlternateException, RequiredExchangeException
@@ -777,9 +838,11 @@
     }
 
     @Override
-    protected void beforeClose()
+    protected ListenableFuture<Void> beforeClose()
     {
         setState(State.UNAVAILABLE);
+
+        return super.beforeClose();
     }
 
     @Override
@@ -1277,37 +1340,76 @@
     }
 
     @StateTransition( currentState = { State.UNINITIALIZED, State.ACTIVE, State.ERRORED }, desiredState = State.STOPPED )
-    protected void doStop()
+    protected ListenableFuture<Void> doStop()
     {
-        closeChildren();
-        shutdownHouseKeeping();
-        closeMessageStore();
-        setState(State.STOPPED);
+        final SettableFuture<Void> returnVal = SettableFuture.create();
+        closeChildren().addListener(
+                new Runnable()
+                {
+                    @Override
+                    public void run()
+                    {
+                        try
+                        {
+                            shutdownHouseKeeping();
+                            closeMessageStore();
+                            setState(State.STOPPED);
+
+                        }
+                        finally
+                        {
+                            returnVal.set(null);
+                        }
+                    }
+                }, getTaskExecutor().getExecutor()
+                                   );
+        return returnVal;
     }
 
     @StateTransition( currentState = { State.ACTIVE, State.ERRORED }, desiredState = State.DELETED )
-    private void doDelete()
+    private ListenableFuture<Void> doDelete()
     {
         if(_deleted.compareAndSet(false,true))
         {
+            final SettableFuture<Void> returnVal = SettableFuture.create();
             String hostName = getName();
 
-            close();
+            closeAsync().addListener(
+                    new Runnable()
+                    {
+                        @Override
+                        public void run()
+                        {
+                            try
+                            {
+                                MessageStore ms = getMessageStore();
+                                if (ms != null)
+                                {
+                                    try
+                                    {
+                                        ms.onDelete(AbstractVirtualHost.this);
+                                    }
+                                    catch (Exception e)
+                                    {
+                                        _logger.warn("Exception occurred on message store deletion", e);
+                                    }
+                                }
+                                deleted();
+                                setState(State.DELETED);
+                            }
+                            finally
+                            {
+                                returnVal.set(null);
+                            }
+                        }
+                    }, getTaskExecutor().getExecutor()
+                               );
 
-            MessageStore ms = getMessageStore();
-            if (ms != null)
-            {
-                try
-                {
-                    ms.onDelete(this);
-                }
-                catch (Exception e)
-                {
-                    _logger.warn("Exception occurred on message store deletion", e);
-                }
-            }
-            deleted();
-            setState(State.DELETED);
+            return returnVal;
+        }
+        else
+        {
+            return Futures.immediateFuture(null);
         }
     }
 
@@ -1496,7 +1598,7 @@
     }
 
     @StateTransition( currentState = { State.UNINITIALIZED,State.ERRORED }, desiredState = State.ACTIVE )
-    private void onActivate()
+    private ListenableFuture<Void> onActivate()
     {
         _houseKeepingTasks = new ScheduledThreadPoolExecutor(getHousekeepingThreadCount(), new SuppressingInheritedAccessControlContextThreadFactory());
 
@@ -1516,9 +1618,28 @@
 
         if (isStoreEmpty())
         {
-            createDefaultExchanges();
+            final SettableFuture<Void> returnVal = SettableFuture.create();
+            createDefaultExchanges().addListener(new Runnable()
+            {
+                @Override
+                public void run()
+                {
+                    postCreateDefaultExchangeTasks();
+                    returnVal.set(null);
+                }
+            }, getTaskExecutor().getExecutor());
+            return returnVal;
         }
+        else
+        {
+            postCreateDefaultExchangeTasks();
 
+            return Futures.immediateFuture(null);
+        }
+    }
+
+    private void postCreateDefaultExchangeTasks()
+    {
         if(getContextValue(Boolean.class, USE_ASYNC_RECOVERY))
         {
             _messageStoreRecoverer = new AsynchronousMessageStoreRecoverer();
@@ -1553,9 +1674,32 @@
             scheduleHouseKeepingTask(getHousekeepingCheckPeriod(), _fileSystemSpaceChecker);
         }
     }
+    private static class ChildCounter
+    {
+        private final AtomicInteger _count = new AtomicInteger();
+        private final Runnable _task;
+
+        private ChildCounter(final Runnable task)
+        {
+            _task = task;
+        }
+
+        public void incrementCount()
+        {
+            _count.incrementAndGet();
+        }
+
+        public void decrementCount()
+        {
+            if(_count.decrementAndGet() == 0)
+            {
+                _task.run();
+            }
+        }
+    }
 
     @StateTransition( currentState = { State.STOPPED, State.ERRORED }, desiredState = State.ACTIVE )
-    private void onRestart()
+    private ListenableFuture<Void> onRestart()
     {
         resetStatistics();
 
@@ -1586,6 +1730,25 @@
 
         new GenericRecoverer(this).recover(records);
 
+        final SettableFuture<Void> returnVal = SettableFuture.create();
+        final ChildCounter counter = new ChildCounter(new Runnable()
+        {
+            @Override
+            public void run()
+            {
+                onActivate().addListener(
+                        new Runnable()
+                        {
+                            @Override
+                            public void run()
+                            {
+                                returnVal.set(null);
+                            }
+                        }, getTaskExecutor().getExecutor()
+                                        );
+            }
+        });
+        counter.incrementCount();
         Subject.doAs(SecurityManager.getSubjectWithAddedSystemRights(), new PrivilegedAction<Object>()
         {
             @Override
@@ -1596,14 +1759,22 @@
                     @Override
                     public void performAction(final ConfiguredObject<?> object)
                     {
-                        object.open();
+                        counter.incrementCount();
+                        object.openAsync().addListener(new Runnable()
+                        {
+                            @Override
+                            public void run()
+                            {
+                                counter.decrementCount();
+                            }
+                        }, getTaskExecutor().getExecutor());
                     }
                 });
                 return null;
             }
         });
-
-        onActivate();
+        counter.decrementCount();
+        return returnVal;
     }
 
     private class FileSystemSpaceChecker extends HouseKeepingTask
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/protocol/ServerProtocolEngine.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostUnavailableException.java
similarity index 66%
copy from qpid/java/common/src/main/java/org/apache/qpid/protocol/ServerProtocolEngine.java
copy to qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostUnavailableException.java
index 5c6918e..a0bab0b 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/protocol/ServerProtocolEngine.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostUnavailableException.java
@@ -18,16 +18,16 @@
  * under the License.
  *
  */
-package org.apache.qpid.protocol;
+package org.apache.qpid.server.virtualhost;
 
-import javax.security.auth.Subject;
+import org.apache.qpid.server.util.ConnectionScopedRuntimeException;
 
-public interface ServerProtocolEngine extends ProtocolEngine
+public class VirtualHostUnavailableException extends ConnectionScopedRuntimeException
 {
-    /**
-     * Gets the connection ID associated with this ProtocolEngine
-     */
-    long getConnectionId();
-
-    Subject getSubject();
+    public VirtualHostUnavailableException(VirtualHostImpl<?, ?, ?> host)
+    {
+        super("Virtualhost state "
+              + host.getState()
+              + " prevents the message from being sent");
+    }
 }
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java
index 03c30a9..fd73963 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java
@@ -29,6 +29,8 @@
 
 import javax.security.auth.Subject;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 import org.apache.log4j.Logger;
 
 import org.apache.qpid.server.configuration.IllegalConfigurationException;
@@ -68,7 +70,7 @@
     }
 
     @Override
-    protected void activate()
+    protected ListenableFuture<Void> activate()
     {
         if (LOGGER.isDebugEnabled())
         {
@@ -107,15 +109,21 @@
         if (host != null)
         {
             final VirtualHost<?,?,?> recoveredHost = host;
-            Subject.doAs(SecurityManager.getSubjectWithAddedSystemRights(), new PrivilegedAction<Object>()
-            {
-                @Override
-                public Object run()
-                {
-                    recoveredHost.open();
-                    return null;
-                }
-            });
+            final ListenableFuture<Void> openFuture = Subject.doAs(SecurityManager.getSubjectWithAddedSystemRights(),
+                                                                   new PrivilegedAction<ListenableFuture<Void>>()
+                                                                   {
+                                                                       @Override
+                                                                       public ListenableFuture<Void> run()
+                                                                       {
+                                                                           return recoveredHost.openAsync();
+
+                                                                       }
+                                                                   });
+            return openFuture;
+        }
+        else
+        {
+            return Futures.immediateFuture(null);
         }
     }
 
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java
index a343b71..8e08554 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java
@@ -37,6 +37,10 @@
 import java.util.Set;
 import java.util.UUID;
 
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
 import org.apache.log4j.Logger;
 
 import org.apache.qpid.exchange.ExchangeDefaults;
@@ -119,16 +123,47 @@
     }
 
     @StateTransition( currentState = {State.UNINITIALIZED, State.STOPPED, State.ERRORED }, desiredState = State.ACTIVE )
-    protected void doActivate()
+    protected ListenableFuture<Void> doActivate()
     {
+        final SettableFuture<Void> returnVal = SettableFuture.create();
+
         try
         {
-            activate();
-            setState(State.ACTIVE);
+            Futures.addCallback(activate(),
+                                new FutureCallback<Void>()
+                                {
+                                    @Override
+                                    public void onSuccess(final Void result)
+                                    {
+                                        try
+                                        {
+                                            setState(State.ACTIVE);
+                                        }
+                                        finally
+                                        {
+                                            returnVal.set(null);
+                                        }
+
+                                    }
+
+                                    @Override
+                                    public void onFailure(final Throwable t)
+                                    {
+
+                                        setState(State.ERRORED);
+                                        returnVal.set(null);
+                                        if (_broker.isManagementMode())
+                                        {
+                                            LOGGER.warn("Failed to make " + this + " active.", t);
+                                        }
+                                    }
+                                }, getTaskExecutor().getExecutor()
+                               );
         }
         catch(RuntimeException e)
         {
             setState(State.ERRORED);
+            returnVal.set(null);
             if (_broker.isManagementMode())
             {
                 LOGGER.warn("Failed to make " + this + " active.", e);
@@ -138,6 +173,7 @@
                 throw e;
             }
         }
+        return returnVal;
     }
 
     @Override
@@ -180,39 +216,73 @@
     }
 
     @StateTransition( currentState = { State.ACTIVE, State.STOPPED, State.ERRORED}, desiredState = State.DELETED )
-    protected void doDelete()
+    protected ListenableFuture<Void> doDelete()
     {
+        final SettableFuture<Void> returnVal = SettableFuture.create();
         setState(State.DELETED);
         deleteVirtualHostIfExists();
-        close();
-        deleted();
-        DurableConfigurationStore configurationStore = getConfigurationStore();
-        if (configurationStore != null)
+        final ListenableFuture<Void> closeFuture = closeAsync();
+        closeFuture.addListener(new Runnable()
         {
-            configurationStore.onDelete(this);
-        }
+            @Override
+            public void run()
+            {
+                try
+                {
+                    deleted();
+                    DurableConfigurationStore configurationStore = getConfigurationStore();
+                    if (configurationStore != null)
+                    {
+                        configurationStore.onDelete(AbstractVirtualHostNode.this);
+                    }
+                }
+                finally
+                {
+                    returnVal.set(null);
+                }
+            }
+        }, getTaskExecutor().getExecutor());
+
+        return returnVal;
+
     }
 
-    protected void deleteVirtualHostIfExists()
+    protected ListenableFuture<Void> deleteVirtualHostIfExists()
     {
         VirtualHost<?, ?, ?> virtualHost = getVirtualHost();
         if (virtualHost != null)
         {
-            virtualHost.delete();
+            return virtualHost.deleteAsync();
+        }
+        else
+        {
+            return Futures.immediateFuture(null);
         }
     }
 
     @StateTransition( currentState = { State.ACTIVE, State.ERRORED, State.UNINITIALIZED }, desiredState = State.STOPPED )
-    protected void doStop()
+    protected ListenableFuture<Void> doStop()
     {
-        stopAndSetStateTo(State.STOPPED);
+        return stopAndSetStateTo(State.STOPPED);
     }
 
-    protected void stopAndSetStateTo(State stoppedState)
+    protected ListenableFuture<Void> stopAndSetStateTo(final State stoppedState)
     {
-        closeChildren();
-        closeConfigurationStoreSafely();
-        setState(stoppedState);
+        final SettableFuture<Void> returnVal = SettableFuture.create();
+
+        ListenableFuture<Void> childCloseFuture = closeChildren();
+        childCloseFuture.addListener(new Runnable()
+        {
+            @Override
+            public void run()
+            {
+                closeConfigurationStoreSafely();
+                setState(stoppedState);
+                returnVal.set(null);
+            }
+        }, getTaskExecutor().getExecutor());
+
+        return returnVal;
     }
 
     @Override
@@ -270,7 +340,7 @@
 
     protected abstract DurableConfigurationStore createConfigurationStore();
 
-    protected abstract void activate();
+    protected abstract ListenableFuture<Void> activate();
 
 
 
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/RedirectingVirtualHostNodeImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/RedirectingVirtualHostNodeImpl.java
index c94d113..8a160f8 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/RedirectingVirtualHostNodeImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/RedirectingVirtualHostNodeImpl.java
@@ -24,6 +24,8 @@
 import java.util.Collections;
 import java.util.Map;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -63,7 +65,7 @@
     }
 
     @StateTransition( currentState = {State.UNINITIALIZED, State.STOPPED, State.ERRORED }, desiredState = State.ACTIVE )
-    protected void doActivate()
+    protected ListenableFuture<Void> doActivate()
     {
         try
         {
@@ -83,6 +85,7 @@
                 throw e;
             }
         }
+        return Futures.immediateFuture(null);
     }
 
     @Override
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/updater/CurrentThreadTaskExecutor.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/updater/CurrentThreadTaskExecutor.java
index 4343419..2664572 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/updater/CurrentThreadTaskExecutor.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/updater/CurrentThreadTaskExecutor.java
@@ -22,11 +22,14 @@
 
 import java.util.concurrent.CancellationException;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicReference;
 
+import com.google.common.util.concurrent.MoreExecutors;
+
 public class CurrentThreadTaskExecutor implements TaskExecutor
 {
     private final AtomicReference<Thread> _thread = new AtomicReference<>();
@@ -144,4 +147,15 @@
         return executor;
     }
 
+    @Override
+    public boolean isTaskExecutorThread()
+    {
+        return true;
+    }
+
+    @Override
+    public Executor getExecutor()
+    {
+        return MoreExecutors.sameThreadExecutor();
+    }
 }
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/consumer/MockConsumer.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/consumer/MockConsumer.java
index 497a66a..d625fcb 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/consumer/MockConsumer.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/consumer/MockConsumer.java
@@ -184,6 +184,18 @@
         return size;
     }
 
+    @Override
+    public boolean hasMessagesToSend()
+    {
+        return false;
+    }
+
+    @Override
+    public void sendNextMessage()
+    {
+
+    }
+
     public void flushBatched()
     {
 
@@ -211,6 +223,12 @@
        close();
     }
 
+    @Override
+    public void notifyCurrentState()
+    {
+
+    }
+
     public void setState(State state)
     {
         State oldState = _state;
@@ -236,6 +254,12 @@
         }
     }
 
+    @Override
+    public void processPending()
+    {
+
+    }
+
     public ArrayList<MessageInstance> getMessages()
     {
         return messages;
@@ -462,6 +486,18 @@
         {
             return 0;
         }
+
+        @Override
+        public void transportStateChanged()
+        {
+
+        }
+
+        @Override
+        public void processPending()
+        {
+
+        }
     }
 
     private static class MockConnectionModel implements AMQConnectionModel
@@ -508,13 +544,13 @@
         }
 
         @Override
-        public void close(AMQConstant cause, String message)
+        public void closeAsync(AMQConstant cause, String message)
         {
         }
 
         @Override
-        public void closeSession(AMQSessionModel session, AMQConstant cause,
-                String message)
+        public void closeSessionAsync(AMQSessionModel session, AMQConstant cause,
+                                      String message)
         {
         }
 
@@ -594,6 +630,18 @@
         }
 
         @Override
+        public void notifyWork()
+        {
+
+        }
+
+        @Override
+        public boolean isMessageAssignmentSuspended()
+        {
+            return false;
+        }
+
+        @Override
         public String getClientVersion()
         {
             return null;
@@ -669,5 +717,7 @@
         {
 
         }
+
+
     }
 }
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java
index 889984e..b2d35f6 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java
@@ -151,6 +151,7 @@
         _count++;
         _queue = mock(AMQQueue.class);
         TaskExecutor executor = new CurrentThreadTaskExecutor();
+        executor.start();
         VirtualHostImpl vhost = mock(VirtualHostImpl.class);
         when(_queue.getVirtualHost()).thenReturn(vhost);
         when(_queue.getModel()).thenReturn(BrokerModel.getInstance());
@@ -158,6 +159,7 @@
         when(vhost.getSecurityManager()).thenReturn(mock(org.apache.qpid.server.security.SecurityManager.class));
         final EventLogger eventLogger = new EventLogger();
         when(vhost.getEventLogger()).thenReturn(eventLogger);
+        when(vhost.getTaskExecutor()).thenReturn(executor);
         _exchange = mock(ExchangeImpl.class);
         when(_exchange.getType()).thenReturn(ExchangeDefaults.HEADERS_EXCHANGE_CLASS);
         when(_exchange.getEventLogger()).thenReturn(eventLogger);
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/actors/BaseConnectionActorTestCase.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/actors/BaseConnectionActorTestCase.java
index 65f9b4b..e62a16f 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/actors/BaseConnectionActorTestCase.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/actors/BaseConnectionActorTestCase.java
@@ -55,7 +55,7 @@
             }
             if (_session != null)
             {
-                _session.close(AMQConstant.CONNECTION_FORCED, "");
+                _session.closeAsync(AMQConstant.CONNECTION_FORCED, "");
             }
         }
         finally
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java
index 20f6e31..4acc925 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java
@@ -22,6 +22,7 @@
 
 import static java.util.Arrays.asList;
 import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.argThat;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doAnswer;
@@ -33,12 +34,15 @@
 import static org.mockito.Mockito.when;
 
 import java.security.AccessControlException;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 
+import org.mockito.ArgumentCaptor;
 import org.mockito.ArgumentMatcher;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
@@ -55,6 +59,7 @@
 import org.apache.qpid.server.store.ConfiguredObjectRecord;
 import org.apache.qpid.server.store.DurableConfigurationStore;
 import org.apache.qpid.server.store.handler.ConfiguredObjectRecordHandler;
+import org.apache.qpid.server.util.Action;
 import org.apache.qpid.server.util.BrokerTestHelper;
 import org.apache.qpid.server.virtualhost.TestMemoryVirtualHost;
 import org.apache.qpid.test.utils.QpidTestCase;
@@ -259,7 +264,7 @@
                      0,
                      virtualHost.getChildren(Connection.class).size());
 
-        verify(connection).close(AMQConstant.CONNECTION_FORCED, "Connection closed by external action");
+        verify(connection).closeAsync(AMQConstant.CONNECTION_FORCED, "Connection closed by external action");
     }
 
     public void testDeleteVirtualHost_ClosesConnections()
@@ -284,7 +289,7 @@
                      0,
                      virtualHost.getChildren(Connection.class).size());
 
-        verify(connection).close(AMQConstant.CONNECTION_FORCED, "Connection closed by external action");
+        verify(connection).closeAsync(AMQConstant.CONNECTION_FORCED, "Connection closed by external action");
     }
 
     public void testCreateDurableQueue()
@@ -409,7 +414,30 @@
     private AMQConnectionModel createMockProtocolConnection(final VirtualHost<?, ?, ?> virtualHost)
     {
         final AMQConnectionModel connection = mock(AMQConnectionModel.class);
+        final List<Action<?>> tasks = new ArrayList<>();
+        final ArgumentCaptor<Action> deleteTaskCaptor = ArgumentCaptor.forClass(Action.class);
+        Answer answer = new Answer()
+        {
+            @Override
+            public Object answer(final InvocationOnMock invocation) throws Throwable
+            {
+                return tasks.add(deleteTaskCaptor.getValue());
+            }
+        };
+        doAnswer(answer).when(connection).addDeleteTask(deleteTaskCaptor.capture());
         when(connection.getVirtualHost()).thenReturn(virtualHost);
+        doAnswer(new Answer()
+        {
+            @Override
+            public Object answer(final InvocationOnMock invocation) throws Throwable
+            {
+                for(Action action : tasks)
+                {
+                    action.performAction(connection);
+                }
+                return null;
+            }
+        }).when(connection).closeAsync(any(AMQConstant.class),anyString());
         when(connection.getRemoteAddressString()).thenReturn("peer:1234");
         return connection;
     }
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/port/AmqpPortImplTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/port/AmqpPortImplTest.java
index c153f31..4df5fb5 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/port/AmqpPortImplTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/port/AmqpPortImplTest.java
@@ -91,6 +91,10 @@
         {
             if (_port != null)
             {
+                while(_port.getConnectionCount() >0)
+                {
+                    _port.decrementConnectionCount();
+                }
                 _port.close();
             }
             super.tearDown();
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/lifecycle/TestConfiguredObject.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/lifecycle/TestConfiguredObject.java
index f905a98..aa4e611 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/lifecycle/TestConfiguredObject.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/lifecycle/TestConfiguredObject.java
@@ -26,6 +26,9 @@
 import java.util.Collections;
 import java.util.Map;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
 import org.apache.qpid.server.configuration.IllegalConfigurationException;
 import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
 import org.apache.qpid.server.configuration.updater.TaskExecutor;
@@ -137,15 +140,17 @@
     }
 
     @StateTransition( currentState = {State.ERRORED, State.UNINITIALIZED}, desiredState = State.ACTIVE )
-    protected void activate()
+    protected ListenableFuture<Void> activate()
     {
         setState(State.ACTIVE);
+        return Futures.immediateFuture(null);
     }
 
     @StateTransition( currentState = {State.ERRORED, State.UNINITIALIZED}, desiredState = State.DELETED )
-    protected void doDelete()
+    protected ListenableFuture<Void> doDelete()
     {
         setState(State.DELETED);
+        return Futures.immediateFuture(null);
     }
 
     public boolean isOpened()
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/AbstractQueueTestBase.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/AbstractQueueTestBase.java
index c1a9240..7667267 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/AbstractQueueTestBase.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/AbstractQueueTestBase.java
@@ -31,14 +31,12 @@
 import static org.mockito.Mockito.when;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.UUID;
 
 import org.apache.log4j.Logger;
 import org.mockito.ArgumentCaptor;
@@ -56,7 +54,6 @@
 import org.apache.qpid.server.message.MessageReference;
 import org.apache.qpid.server.message.MessageSource;
 import org.apache.qpid.server.message.ServerMessage;
-import org.apache.qpid.server.model.LifetimePolicy;
 import org.apache.qpid.server.model.Queue;
 import org.apache.qpid.server.model.QueueNotificationListener;
 import org.apache.qpid.server.model.UUIDGenerator;
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/txn/AsyncAutoCommitTransactionTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/txn/AsyncAutoCommitTransactionTest.java
index ec0908e..a61ac4f 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/txn/AsyncAutoCommitTransactionTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/txn/AsyncAutoCommitTransactionTest.java
@@ -27,7 +27,7 @@
 import org.apache.qpid.server.queue.BaseQueue;
 import org.apache.qpid.server.store.MessageDurability;
 import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.StoreFuture;
+import org.apache.qpid.server.util.FutureResult;
 import org.apache.qpid.server.store.Transaction;
 import org.apache.qpid.server.txn.AsyncAutoCommitTransaction.FutureRecorder;
 import org.apache.qpid.server.txn.ServerTransaction.Action;
@@ -43,7 +43,7 @@
     private MessageStore _messageStore = mock(MessageStore.class);
     private Transaction _storeTransaction = mock(Transaction.class);
     private Action _postTransactionAction = mock(Action.class);
-    private StoreFuture _future = mock(StoreFuture.class);
+    private FutureResult _future = mock(FutureResult.class);
 
 
     @Override
@@ -136,7 +136,7 @@
         asyncAutoCommitTransaction.enqueue(_queue, _message, _postTransactionAction);
 
         verifyZeroInteractions(_storeTransaction);
-        verify(_futureRecorder).recordFuture(StoreFuture.IMMEDIATE_FUTURE, _postTransactionAction);
+        verify(_futureRecorder).recordFuture(FutureResult.IMMEDIATE_FUTURE, _postTransactionAction);
         verifyZeroInteractions(_postTransactionAction);
     }
 }
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java
index da868a0..6fcfde0 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java
@@ -24,7 +24,7 @@
 import org.apache.qpid.server.message.EnqueueableMessage;
 import org.apache.qpid.server.store.MessageStore;
 import org.apache.qpid.server.store.NullMessageStore;
-import org.apache.qpid.server.store.StoreFuture;
+import org.apache.qpid.server.util.FutureResult;
 import org.apache.qpid.server.store.Transaction;
 import org.apache.qpid.server.store.TransactionLogResource;
 import org.apache.qpid.server.util.ServerScopedRuntimeException;
@@ -96,7 +96,7 @@
         _state = TransactionState.COMMITTED;
     }
 
-    public StoreFuture commitTranAsync()
+    public FutureResult commitTranAsync()
     {
         throw new NotImplementedException();
     }
@@ -126,4 +126,4 @@
             }
        };
     }
-}
\ No newline at end of file
+}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/AbstractVirtualHostTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/AbstractVirtualHostTest.java
index 9a7f1fc..5a99538 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/AbstractVirtualHostTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/AbstractVirtualHostTest.java
@@ -22,17 +22,13 @@
 
 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 static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
-import java.io.File;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.qpid.server.configuration.IllegalConfigurationException;
@@ -91,7 +87,7 @@
         {
             if (_taskExecutor != null)
             {
-                _taskExecutor.stopImmediately();
+                _taskExecutor.stop();
             }
         }
         finally
@@ -180,7 +176,7 @@
         verify(store, times(0)).closeMessageStore();
     }
 
-    public void testDeleteInErrorStateAfterOpen()
+    public void testDeleteInErrorStateAfterOpen() throws Exception
     {
         Map<String,Object> attributes = Collections.<String, Object>singletonMap(AbstractVirtualHost.NAME, getTestName());
         AbstractVirtualHost host = new AbstractVirtualHost(attributes, _node)
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java
index e799f62..deb93d6 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java
@@ -35,6 +35,9 @@
 import java.util.UUID;
 import java.util.concurrent.atomic.AtomicBoolean;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
 import org.apache.qpid.server.configuration.IllegalConfigurationException;
 import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
 import org.apache.qpid.server.configuration.updater.TaskExecutor;
@@ -553,8 +556,9 @@
         }
 
         @Override
-        protected void activate()
+        protected ListenableFuture<Void> activate()
         {
+            return Futures.immediateFuture(null);
         }
 
         @Override
diff --git a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImpl.java b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImpl.java
index 0904379..99db75a 100644
--- a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImpl.java
+++ b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImpl.java
@@ -25,6 +25,9 @@
 import java.util.Map;
 import java.util.Set;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
 import org.apache.log4j.Logger;
 
 import org.apache.qpid.server.configuration.IllegalConfigurationException;
@@ -149,7 +152,7 @@
 
 
     @StateTransition(currentState = {State.UNINITIALIZED, State.QUIESCED, State.ERRORED}, desiredState = State.ACTIVE)
-    private void activate()
+    private ListenableFuture<Void> activate()
     {
 
         if(_broker.isManagementMode())
@@ -177,6 +180,7 @@
                 }
             }
         }
+        return Futures.immediateFuture(null);
     }
 
     @Override
@@ -190,17 +194,36 @@
     }
 
     @StateTransition(currentState = State.UNINITIALIZED, desiredState = State.QUIESCED)
-    private void startQuiesced()
+    private ListenableFuture<Void> startQuiesced()
     {
         setState(State.QUIESCED);
+        return Futures.immediateFuture(null);
     }
 
     @StateTransition(currentState = {State.ACTIVE, State.QUIESCED, State.ERRORED}, desiredState = State.DELETED)
-    private void doDelete()
+    private ListenableFuture<Void> doDelete()
     {
-        close();
-        setState(State.DELETED);
-        deleted();
+        final SettableFuture<Void> returnVal = SettableFuture.create();
+        closeAsync().addListener(
+                new Runnable()
+                {
+                    @Override
+                    public void run()
+                    {
+                        try
+                        {
+
+                            setState(State.DELETED);
+                            deleted();
+                        }
+                        finally
+                        {
+                            returnVal.set(null);
+                        }
+                    }
+                }, getTaskExecutor().getExecutor()
+                           );
+        return returnVal;
     }
 
     public AccessControl getAccessControl()
diff --git a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderFactoryTest.java b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderFactoryTest.java
index a34ac16..2a691b3 100644
--- a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderFactoryTest.java
+++ b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderFactoryTest.java
@@ -30,6 +30,7 @@
 import java.util.regex.Pattern;
 
 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.AccessControlProvider;
 import org.apache.qpid.server.model.Broker;
@@ -54,7 +55,9 @@
         when(_broker.getObjectFactory()).thenReturn(_objectFactory);
         when(_broker.getModel()).thenReturn(_objectFactory.getModel());
         when(_broker.getCategoryClass()).thenReturn(Broker.class);
-        when(_broker.getTaskExecutor()).thenReturn(mock(TaskExecutor.class));
+        TaskExecutor taskExecutor = new CurrentThreadTaskExecutor();
+        taskExecutor.start();
+        when(_broker.getTaskExecutor()).thenReturn(taskExecutor);
     }
 
     public void testCreateInstanceWhenAclFileIsNotPresent()
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ConsumerTarget_0_10.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ConsumerTarget_0_10.java
index 89d6811..5affe30 100644
--- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ConsumerTarget_0_10.java
+++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ConsumerTarget_0_10.java
@@ -104,7 +104,8 @@
         _name = name;
     }
 
-    public boolean isSuspended()
+    @Override
+    public boolean doIsSuspended()
     {
         return getState()!=State.ACTIVE || _deleted.get() || _session.isClosing() || _session.getConnectionModel().isStopped(); // TODO check for Session suspension
     }
@@ -158,6 +159,10 @@
         return _name;
     }
 
+    public void transportStateChanged()
+    {
+        _creditManager.restoreCredit(0, 0);
+    }
 
     public static class AddMessageDispositionListenerAction implements Runnable
     {
@@ -191,7 +196,7 @@
 
     private final AddMessageDispositionListenerAction _postIdSettingAction;
 
-    public long send(final ConsumerImpl consumer, final MessageInstance entry, boolean batch)
+    public void doSend(final ConsumerImpl consumer, final MessageInstance entry, boolean batch)
     {
         ServerMessage serverMsg = entry.getMessage();
 
@@ -342,7 +347,6 @@
         {
             recordUnacknowledged(entry);
         }
-        return size;
     }
 
     void recordUnacknowledged(MessageInstance entry)
@@ -555,10 +559,10 @@
         switch(flowMode)
         {
             case CREDIT:
-                _creditManager = new CreditCreditManager(0l,0l);
+                _creditManager = new CreditCreditManager(0l, 0l, _session.getConnection().getProtocolEngine());
                 break;
             case WINDOW:
-                _creditManager = new WindowCreditManager(0l,0l);
+                _creditManager = new WindowCreditManager(0l, 0l, _session.getConnection().getProtocolEngine());
                 break;
             default:
                 // this should never happen, as 0-10 is finalised and so the enum should never change
@@ -628,7 +632,6 @@
 
     public void flushBatched()
     {
-        _session.getConnection().flush();
     }
 
 
@@ -657,4 +660,10 @@
     {
         return _unacknowledgedCount.longValue();
     }
+
+    @Override
+    protected void processClosed()
+    {
+
+    }
 }
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/CreditCreditManager.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/CreditCreditManager.java
index 8dddac9..dd43ae7 100644
--- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/CreditCreditManager.java
+++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/CreditCreditManager.java
@@ -21,48 +21,27 @@
 package org.apache.qpid.server.protocol.v0_10;
 
 
+import org.apache.qpid.server.protocol.ServerProtocolEngine;
 import org.apache.qpid.server.flow.AbstractFlowCreditManager;
 
 public class CreditCreditManager extends AbstractFlowCreditManager implements FlowCreditManager_0_10
 {
+    private final ServerProtocolEngine _serverProtocolEngine;
     private volatile long _bytesCredit;
     private volatile long _messageCredit;
 
-    public CreditCreditManager(long bytesCredit, long messageCredit)
+    public CreditCreditManager(long bytesCredit, long messageCredit, final ServerProtocolEngine serverProtocolEngine)
     {
+        _serverProtocolEngine = serverProtocolEngine;
         _bytesCredit = bytesCredit;
         _messageCredit = messageCredit;
         setSuspended(!hasCredit());
 
     }
 
-
-    public synchronized void setCreditLimits(final long bytesCredit, final long messageCredit)
-    {
-        _bytesCredit = bytesCredit;
-        _messageCredit = messageCredit;
-
-        setSuspended(!hasCredit());
-
-    }
-
-
-    public long getMessageCredit()
-    {
-         return _messageCredit == -1L
-                    ? Long.MAX_VALUE
-                    : _messageCredit;
-    }
-
-    public long getBytesCredit()
-    {
-        return _bytesCredit == -1L
-                    ? Long.MAX_VALUE
-                    : _bytesCredit;
-    }
-
     public synchronized void restoreCredit(final long messageCredit, final long bytesCredit)
     {
+        setSuspended(!hasCredit());
     }
 
 
@@ -107,12 +86,17 @@
     public synchronized boolean hasCredit()
     {
         // Note !=, if credit is < 0 that indicates infinite credit
-        return (_bytesCredit != 0L  && _messageCredit != 0L);
+        return (_bytesCredit != 0L  && _messageCredit != 0L && !_serverProtocolEngine.isTransportBlockedForWriting());
     }
 
     public synchronized boolean useCreditForMessage(long msgSize)
     {
-        if(_messageCredit >= 0L)
+        if (_serverProtocolEngine.isTransportBlockedForWriting())
+        {
+            setSuspended(true);
+            return false;
+        }
+        else if(_messageCredit >= 0L)
         {
             if(_messageCredit > 0)
             {
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ProtocolEngineCreator_0_10.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ProtocolEngineCreator_0_10.java
index 30aecdb..4231045 100644
--- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ProtocolEngineCreator_0_10.java
+++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ProtocolEngineCreator_0_10.java
@@ -23,7 +23,7 @@
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
 
-import org.apache.qpid.protocol.ServerProtocolEngine;
+import org.apache.qpid.server.protocol.ServerProtocolEngine;
 import org.apache.qpid.server.model.Broker;
 import org.apache.qpid.server.model.Protocol;
 import org.apache.qpid.server.model.Transport;
@@ -86,7 +86,10 @@
         conn.setRemoteAddress(network.getRemoteAddress());
         conn.setLocalAddress(network.getLocalAddress());
 
-        return new ProtocolEngine_0_10( conn, network);
+        ProtocolEngine_0_10 protocolEngine = new ProtocolEngine_0_10(conn, network);
+        conn.setProtocolEngine(protocolEngine);
+
+        return protocolEngine;
     }
 
 
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ProtocolEngine_0_10.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ProtocolEngine_0_10.java
index 854cd38..e391bd6 100755
--- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ProtocolEngine_0_10.java
+++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ProtocolEngine_0_10.java
@@ -24,18 +24,23 @@
 import java.nio.ByteBuffer;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
 
 import javax.security.auth.Subject;
 
 import org.apache.log4j.Logger;
 
-import org.apache.qpid.protocol.ServerProtocolEngine;
+import org.apache.qpid.server.protocol.ServerProtocolEngine;
+import org.apache.qpid.server.consumer.ConsumerImpl;
 import org.apache.qpid.server.logging.messages.ConnectionMessages;
+import org.apache.qpid.server.model.Consumer;
 import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.protocol.AMQSessionModel;
+import org.apache.qpid.server.util.Action;
+import org.apache.qpid.transport.ByteBufferSender;
 import org.apache.qpid.transport.Constant;
-import org.apache.qpid.transport.Sender;
 import org.apache.qpid.transport.network.Assembler;
-import org.apache.qpid.transport.network.Disassembler;
 import org.apache.qpid.transport.network.InputHandler;
 import org.apache.qpid.transport.network.NetworkConnection;
 
@@ -52,13 +57,20 @@
     private ServerConnection _connection;
 
     private long _createTime = System.currentTimeMillis();
-    private long _lastReadTime;
-    private long _lastWriteTime;
+    private long _lastReadTime = _createTime;
+    private long _lastWriteTime = _createTime;
+    private volatile boolean _transportBlockedForWriting;
+
+    private final AtomicReference<Thread> _messageAssignmentSuspended = new AtomicReference<>();
+
+    private final AtomicBoolean _stateChanged = new AtomicBoolean();
+    private final AtomicReference<Action<ServerProtocolEngine>> _workListener = new AtomicReference<>();
+
 
     public ProtocolEngine_0_10(ServerConnection conn,
                                NetworkConnection network)
     {
-        super(new Assembler(conn));
+        super(new ServerAssembler(conn));
         _connection = conn;
 
         if(network != null)
@@ -67,7 +79,33 @@
         }
     }
 
-    public void setNetworkConnection(final NetworkConnection network, final Sender<ByteBuffer> sender)
+    @Override
+    public boolean isMessageAssignmentSuspended()
+    {
+        Thread lock = _messageAssignmentSuspended.get();
+        return lock != null && _messageAssignmentSuspended.get() != Thread.currentThread();
+    }
+
+    @Override
+    public void setMessageAssignmentSuspended(final boolean messageAssignmentSuspended)
+    {
+        _messageAssignmentSuspended.set(messageAssignmentSuspended ? Thread.currentThread() : null);
+
+        if(!messageAssignmentSuspended)
+        {
+           for(AMQSessionModel<?,?> session : _connection.getSessionModels())
+           {
+               for(Consumer<?> consumer : session.getConsumers())
+               {
+                   ((ConsumerImpl)consumer).getTarget().notifyCurrentState();
+               }
+           }
+        }
+    }
+
+
+
+    public void setNetworkConnection(final NetworkConnection network, final ByteBufferSender sender)
     {
         if(!getSubject().equals(Subject.getSubject(AccessController.getContext())))
         {
@@ -87,7 +125,7 @@
             _network = network;
 
             _connection.setNetworkConnection(network);
-            Disassembler disassembler = new Disassembler(wrapSender(sender), Constant.MIN_MAX_FRAME_SIZE);
+            ServerDisassembler disassembler = new ServerDisassembler(wrapSender(sender), Constant.MIN_MAX_FRAME_SIZE);
             _connection.setSender(disassembler);
             _connection.addFrameSizeObserver(disassembler);
             // FIXME Two log messages to maintain compatibility with earlier protocol versions
@@ -96,23 +134,15 @@
         }
     }
 
-    private Sender<ByteBuffer> wrapSender(final Sender<ByteBuffer> sender)
+    private ByteBufferSender wrapSender(final ByteBufferSender sender)
     {
-        return new Sender<ByteBuffer>()
+        return new ByteBufferSender()
         {
             @Override
-            public void setIdleTimeout(int i)
-            {
-                sender.setIdleTimeout(i);
-
-            }
-
-            @Override
             public void send(ByteBuffer msg)
             {
                 _lastWriteTime = System.currentTimeMillis();
                 sender.send(msg);
-
             }
 
             @Override
@@ -190,6 +220,11 @@
         return _writtenBytes;
     }
 
+    @Override
+    public void encryptedTransport()
+    {
+    }
+
     public void writerIdle()
     {
         _connection.doHeartBeat();
@@ -215,11 +250,6 @@
         return getRemoteAddress().toString();
     }
 
-    public String getAuthId()
-    {
-        return _connection.getAuthorizedPrincipal() == null ? null : _connection.getAuthorizedPrincipal().getName();
-    }
-
     public boolean isDurable()
     {
         return false;
@@ -246,4 +276,54 @@
     {
         return _connection.getAuthorizedSubject();
     }
+
+    @Override
+    public boolean isTransportBlockedForWriting()
+    {
+        return _transportBlockedForWriting;
+    }
+
+    @Override
+    public void setTransportBlockedForWriting(final boolean blocked)
+    {
+        _transportBlockedForWriting = blocked;
+        _connection.transportStateChanged();
+    }
+
+    @Override
+    public void processPending()
+    {
+        _connection.processPending();
+
+    }
+
+    @Override
+    public boolean hasWork()
+    {
+        return _stateChanged.get();
+    }
+
+    @Override
+    public void notifyWork()
+    {
+        _stateChanged.set(true);
+
+        final Action<ServerProtocolEngine> listener = _workListener.get();
+        if(listener != null)
+        {
+            listener.performAction(this);
+        }
+    }
+
+    @Override
+    public void clearWork()
+    {
+        _stateChanged.set(false);
+    }
+
+    @Override
+    public void setWorkListener(final Action<ServerProtocolEngine> listener)
+    {
+        _workListener.set(listener);
+    }
 }
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerAssembler.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerAssembler.java
new file mode 100644
index 0000000..456c9d3
--- /dev/null
+++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerAssembler.java
@@ -0,0 +1,57 @@
+/*
+ *
+ * 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_10;
+
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.qpid.transport.network.Assembler;
+import org.apache.qpid.transport.network.NetworkEvent;
+
+public class ServerAssembler extends Assembler
+{
+    private static final Logger LOGGER = LoggerFactory.getLogger(ServerAssembler.class);
+
+
+    private final ServerConnection _connection;
+
+    public ServerAssembler(final ServerConnection connection)
+    {
+        super(connection);
+        _connection = connection;
+    }
+
+    @Override
+    public void received(final NetworkEvent event)
+    {
+        if (!_connection.isIgnoreFutureInput())
+        {
+            super.received(event);
+        }
+        else
+        {
+            LOGGER.debug("Ignored network event " + event + " as connection is ignoring further input ");
+        }
+    }
+
+
+}
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnection.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnection.java
index 8567be3..2280377 100644
--- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnection.java
+++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnection.java
@@ -23,6 +23,7 @@
 import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CONNECTION_FORMAT;
 import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.SOCKET_FORMAT;
 import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.USER_FORMAT;
+import static org.apache.qpid.transport.Connection.State.CLOSING;
 
 import java.net.SocketAddress;
 import java.security.Principal;
@@ -30,6 +31,8 @@
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
@@ -37,6 +40,7 @@
 import javax.security.auth.Subject;
 
 import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.server.protocol.ServerProtocolEngine;
 import org.apache.qpid.server.connection.ConnectionPrincipal;
 import org.apache.qpid.server.logging.EventLogger;
 import org.apache.qpid.server.logging.LogSubject;
@@ -66,7 +70,6 @@
 {
 
     private final Broker<?> _broker;
-    private Runnable _onOpenTask;
     private AtomicBoolean _logClosed = new AtomicBoolean(false);
 
     private final Subject _authorizedSubject = new Subject();
@@ -75,20 +78,26 @@
     private final long _connectionId;
     private final Object _reference = new Object();
     private VirtualHostImpl<?,?,?> _virtualHost;
-    private AmqpPort<?> _port;
-    private AtomicLong _lastIoTime = new AtomicLong();
+    private final AmqpPort<?> _port;
+    private final AtomicLong _lastIoTime = new AtomicLong();
     private boolean _blocking;
-    private Transport _transport;
+    private final Transport _transport;
 
-    private final CopyOnWriteArrayList<Action<? super ServerConnection>> _taskList =
+    private final CopyOnWriteArrayList<Action<? super ServerConnection>> _connectionCloseTaskList =
             new CopyOnWriteArrayList<Action<? super ServerConnection>>();
 
+    private final Queue<Action<? super ServerConnection>> _asyncTaskList =
+            new ConcurrentLinkedQueue<>();
+
     private final CopyOnWriteArrayList<SessionModelListener> _sessionListeners =
             new CopyOnWriteArrayList<SessionModelListener>();
 
     private volatile boolean _stopped;
     private int _messageCompressionThreshold;
-    private int _maxMessageSize;
+    private final int _maxMessageSize;
+
+    private ServerProtocolEngine _serverProtocolEngine;
+    private boolean _ignoreFutureInput;
 
     public ServerConnection(final long connectionId,
                             Broker<?> broker,
@@ -140,10 +149,6 @@
 
         if (state == State.OPEN)
         {
-            if (_onOpenTask != null)
-            {
-                _onOpenTask.run();
-            }
             getEventLogger().message(ConnectionMessages.OPEN(getClientId(),
                                                              "0-10",
                                                              getClientVersion(),
@@ -189,6 +194,16 @@
         super.setConnectionDelegate(delegate);
     }
 
+    public ServerProtocolEngine getProtocolEngine()
+    {
+        return _serverProtocolEngine;
+    }
+
+    public void setProtocolEngine(final ServerProtocolEngine serverProtocolEngine)
+    {
+        _serverProtocolEngine = serverProtocolEngine;
+    }
+
     public VirtualHostImpl<?,?,?> getVirtualHost()
     {
         return _virtualHost;
@@ -237,28 +252,32 @@
         return _stopped;
     }
 
-    public void onOpen(final Runnable task)
+    public void closeSessionAsync(final ServerSession session, final AMQConstant cause, final String message)
     {
-        _onOpenTask = task;
-    }
-
-    public void closeSession(ServerSession session, AMQConstant cause, String message)
-    {
-        ExecutionException ex = new ExecutionException();
-        ExecutionErrorCode code = ExecutionErrorCode.INTERNAL_ERROR;
-        try
+        addAsyncTask(new Action<ServerConnection>()
         {
-	        code = ExecutionErrorCode.get(cause.getCode());
-        }
-        catch (IllegalArgumentException iae)
-        {
-            // Ignore, already set to INTERNAL_ERROR
-        }
-        ex.setErrorCode(code);
-        ex.setDescription(message);
-        session.invoke(ex);
 
-        session.close(cause, message);
+            @Override
+            public void performAction(final ServerConnection conn)
+            {
+                ExecutionException ex = new ExecutionException();
+                ExecutionErrorCode code = ExecutionErrorCode.INTERNAL_ERROR;
+                try
+                {
+                    code = ExecutionErrorCode.get(cause.getCode());
+                }
+                catch (IllegalArgumentException iae)
+                {
+                    // Ignore, already set to INTERNAL_ERROR
+                }
+                ex.setErrorCode(code);
+                ex.setDescription(message);
+                session.invoke(ex);
+
+                session.close(cause, message);
+            }
+        });
+
     }
 
     public LogSubject getLogSubject()
@@ -355,25 +374,35 @@
         }
     }
 
-    public void close(AMQConstant cause, String message)
+    public void closeAsync(final AMQConstant cause, final String message)
     {
-        closeSubscriptions();
-        performDeleteTasks();
-        ConnectionCloseCode replyCode = ConnectionCloseCode.NORMAL;
-        try
+
+        addAsyncTask(new Action<ServerConnection>()
         {
-            replyCode = ConnectionCloseCode.get(cause.getCode());
-        }
-        catch (IllegalArgumentException iae)
-        {
-            // Ignore
-        }
-        close(replyCode, message);
+            @Override
+            public void performAction(final ServerConnection object)
+            {
+                closeSubscriptions();
+                performDeleteTasks();
+
+                setState(CLOSING);
+                ConnectionCloseCode replyCode = ConnectionCloseCode.NORMAL;
+                try
+                {
+                    replyCode = ConnectionCloseCode.get(cause.getCode());
+                }
+                catch (IllegalArgumentException iae)
+                {
+                    // Ignore
+                }
+                sendConnectionClose(replyCode, message);
+            }
+        });
     }
 
     protected void performDeleteTasks()
     {
-        for(Action<? super ServerConnection> task : _taskList)
+        for(Action<? super ServerConnection> task : _connectionCloseTaskList)
         {
             task.performAction(this);
         }
@@ -646,13 +675,19 @@
     @Override
     public void addDeleteTask(final Action<? super ServerConnection> task)
     {
-        _taskList.add(task);
+        _connectionCloseTaskList.add(task);
+    }
+
+    private void addAsyncTask(final Action<ServerConnection> action)
+    {
+        _asyncTaskList.add(action);
+        notifyWork();
     }
 
     @Override
     public void removeDeleteTask(final Action<? super ServerConnection> task)
     {
-        _taskList.remove(task);
+        _connectionCloseTaskList.remove(task);
     }
 
     public int getMessageCompressionThreshold()
@@ -664,4 +699,51 @@
     {
         return _maxMessageSize;
     }
+
+    public void transportStateChanged()
+    {
+        for (AMQSessionModel ssn : getSessionModels())
+        {
+            ssn.transportStateChanged();
+        }
+    }
+
+    @Override
+    public void notifyWork()
+    {
+        _serverProtocolEngine.notifyWork();
+    }
+
+
+    @Override
+    public boolean isMessageAssignmentSuspended()
+    {
+        return _serverProtocolEngine.isMessageAssignmentSuspended();
+    }
+
+    public void processPending()
+    {
+        while(_asyncTaskList.peek() != null)
+        {
+            Action<? super ServerConnection> asyncAction = _asyncTaskList.poll();
+            asyncAction.performAction(this);
+        }
+
+        for (AMQSessionModel session : getSessionModels())
+        {
+            session.processPending();
+        }
+
+    }
+
+    public void closeAndIgnoreFutureInput()
+    {
+        _ignoreFutureInput = true;
+        getSender().close();
+    }
+
+    public boolean isIgnoreFutureInput()
+    {
+        return _ignoreFutureInput;
+    }
 }
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnectionDelegate.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnectionDelegate.java
index 6e2a6ca..7f646b4 100644
--- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnectionDelegate.java
+++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnectionDelegate.java
@@ -250,7 +250,7 @@
                     ") above the server's offered limit (" + getChannelMax() +")");
 
             //Due to the error we must forcefully close the connection without negotiation
-            sconn.getSender().close();
+            sconn.closeAndIgnoreFutureInput();
             return;
         }
 
@@ -261,7 +261,8 @@
                          ") above the server's offered limit (" + getFrameMax() +")");
 
             //Due to the error we must forcefully close the connection without negotiation
-            sconn.getSender().close();
+            sconn.closeAndIgnoreFutureInput();
+
             return;
         }
         else if(okMaxFrameSize > 0 && okMaxFrameSize < Constant.MIN_MAX_FRAME_SIZE)
@@ -271,7 +272,7 @@
                          ") below the minimum permitted size (" + Constant.MIN_MAX_FRAME_SIZE +")");
 
             //Due to the error we must forcefully close the connection without negotiation
-            sconn.getSender().close();
+            sconn.closeAndIgnoreFutureInput();
             return;
         }
         else if(okMaxFrameSize == 0)
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerDisassembler.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerDisassembler.java
new file mode 100644
index 0000000..a42238a
--- /dev/null
+++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerDisassembler.java
@@ -0,0 +1,248 @@
+/*
+ *
+ * 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_10;
+
+import static java.lang.Math.min;
+import static org.apache.qpid.transport.network.Frame.FIRST_FRAME;
+import static org.apache.qpid.transport.network.Frame.FIRST_SEG;
+import static org.apache.qpid.transport.network.Frame.HEADER_SIZE;
+import static org.apache.qpid.transport.network.Frame.LAST_FRAME;
+import static org.apache.qpid.transport.network.Frame.LAST_SEG;
+
+import java.nio.ByteBuffer;
+
+import org.apache.qpid.transport.ByteBufferSender;
+import org.apache.qpid.transport.FrameSizeObserver;
+import org.apache.qpid.transport.Header;
+import org.apache.qpid.transport.Method;
+import org.apache.qpid.transport.ProtocolDelegate;
+import org.apache.qpid.transport.ProtocolError;
+import org.apache.qpid.transport.ProtocolEvent;
+import org.apache.qpid.transport.ProtocolEventSender;
+import org.apache.qpid.transport.ProtocolHeader;
+import org.apache.qpid.transport.SegmentType;
+import org.apache.qpid.transport.Struct;
+import org.apache.qpid.transport.codec.Encoder;
+import org.apache.qpid.transport.network.Frame;
+
+/**
+ * Disassembler
+ */
+public final class ServerDisassembler implements ProtocolEventSender, ProtocolDelegate<Void>, FrameSizeObserver
+{
+    private final ByteBufferSender _sender;
+    private int _maxPayload;
+    private final Object _sendLock = new Object();
+    private final Encoder _encoder =  new ServerEncoder();
+
+    public ServerDisassembler(ByteBufferSender sender, int maxFrame)
+    {
+        _sender = sender;
+        if (maxFrame <= HEADER_SIZE || maxFrame >= 64 * 1024)
+        {
+            throw new IllegalArgumentException("maxFrame must be > HEADER_SIZE and < 64K: " + maxFrame);
+        }
+        _maxPayload = maxFrame - HEADER_SIZE;
+    }
+
+    public void send(ProtocolEvent event)
+    {
+        synchronized (_sendLock)
+        {
+            event.delegate(null, this);
+        }
+    }
+
+    public void flush()
+    {
+        synchronized (_sendLock)
+        {
+            _sender.flush();
+        }
+    }
+
+    public void close()
+    {
+        synchronized (_sendLock)
+        {
+            _sender.close();
+        }
+    }
+
+    private void frame(byte flags, byte type, byte track, int channel, int size, ByteBuffer buf)
+    {
+        ByteBuffer data = ByteBuffer.wrap(new byte[HEADER_SIZE]);
+
+        data.put(0, flags);
+        data.put(1, type);
+        data.putShort(2, (short) (size + HEADER_SIZE));
+        data.put(5, track);
+        data.putShort(6, (short) channel);
+
+
+        ByteBuffer dup = buf.duplicate();
+        dup.limit(dup.position() + size);
+        buf.position(buf.position() + size);
+        _sender.send(data);
+        _sender.send(dup);
+
+
+    }
+
+    private void fragment(byte flags, SegmentType type, ProtocolEvent event, ByteBuffer buf)
+    {
+        byte typeb = (byte) type.getValue();
+        byte track = event.getEncodedTrack() == Frame.L4 ? (byte) 1 : (byte) 0;
+
+        int remaining = buf.remaining();
+        boolean first = true;
+        while (true)
+        {
+            int size = min(_maxPayload, remaining);
+            remaining -= size;
+
+            byte newflags = flags;
+            if (first)
+            {
+                newflags |= FIRST_FRAME;
+                first = false;
+            }
+            if (remaining == 0)
+            {
+                newflags |= LAST_FRAME;
+            }
+
+            frame(newflags, typeb, track, event.getChannel(), size, buf);
+
+            if (remaining == 0)
+            {
+                break;
+            }
+        }
+    }
+
+    public void init(Void v, ProtocolHeader header)
+    {
+        _sender.send(header.toByteBuffer());
+        _sender.flush();
+}
+
+    public void control(Void v, Method method)
+    {
+        method(method, SegmentType.CONTROL);
+    }
+
+    public void command(Void v, Method method)
+    {
+        method(method, SegmentType.COMMAND);
+    }
+
+    private void method(Method method, SegmentType type)
+    {
+        Encoder enc = _encoder;
+        enc.init();
+        enc.writeUint16(method.getEncodedType());
+        if (type == SegmentType.COMMAND)
+        {
+            if (method.isSync())
+            {
+                enc.writeUint16(0x0101);
+            }
+            else
+            {
+                enc.writeUint16(0x0100);
+            }
+        }
+        method.write(enc);
+        int methodLimit = enc.position();
+
+        byte flags = FIRST_SEG;
+
+        boolean payload = method.hasPayload();
+        if (!payload)
+        {
+            flags |= LAST_SEG;
+        }
+
+        int headerLimit = -1;
+        if (payload)
+        {
+            final Header hdr = method.getHeader();
+            if (hdr != null)
+            {
+                if (hdr.getDeliveryProperties() != null)
+                {
+                    enc.writeStruct32(hdr.getDeliveryProperties());
+                }
+                if (hdr.getMessageProperties() != null)
+                {
+                    enc.writeStruct32(hdr.getMessageProperties());
+                }
+                if (hdr.getNonStandardProperties() != null)
+                {
+                    for (Struct st : hdr.getNonStandardProperties())
+                    {
+                        enc.writeStruct32(st);
+                    }
+                }
+            }
+
+            headerLimit = enc.position();
+        }
+        synchronized (_sendLock)
+        {
+            ByteBuffer buf = enc.underlyingBuffer();
+            buf.position(0);
+            buf.limit(methodLimit);
+
+            fragment(flags, type, method, buf.duplicate());
+            if (payload)
+            {
+                ByteBuffer body = method.getBody();
+                buf.limit(headerLimit);
+                buf.position(methodLimit);
+
+                fragment(body == null ? LAST_SEG : 0x0, SegmentType.HEADER, method, buf.duplicate());
+                if (body != null)
+                {
+                    fragment(LAST_SEG, SegmentType.BODY, method, body.duplicate());
+                }
+
+            }
+        }
+    }
+
+    public void error(Void v, ProtocolError error)
+    {
+        throw new IllegalArgumentException(String.valueOf(error));
+    }
+
+    @Override
+    public void setMaxFrameSize(final int maxFrame)
+    {
+        if (maxFrame <= HEADER_SIZE || maxFrame >= 64*1024)
+        {
+            throw new IllegalArgumentException("maxFrame must be > HEADER_SIZE and < 64K: " + maxFrame);
+        }
+        this._maxPayload = maxFrame - HEADER_SIZE;
+
+    }
+}
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerEncoder.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerEncoder.java
new file mode 100644
index 0000000..6437015
--- /dev/null
+++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerEncoder.java
@@ -0,0 +1,371 @@
+/*
+ *
+ * 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_10;
+
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.util.UUID;
+
+import org.apache.qpid.transport.codec.AbstractEncoder;
+
+
+public final class ServerEncoder extends AbstractEncoder
+{
+    public static final int DEFAULT_CAPACITY = 8192;
+    private final int _threshold;
+    private ByteBuffer _out;
+    private int _segment;
+    private int _initialCapacity;
+
+    public ServerEncoder()
+    {
+        this(DEFAULT_CAPACITY);
+    }
+
+    public ServerEncoder(int capacity)
+    {
+        _initialCapacity = capacity;
+        _threshold = capacity/16;
+        _out = ByteBuffer.allocate(capacity);
+        _segment = 0;
+    }
+
+    public void init()
+    {
+        _out.position(_out.limit());
+        _out.limit(_out.capacity());
+        _out = _out.slice();
+        if(_out.remaining() < _threshold)
+        {
+            _out = ByteBuffer.allocate(_initialCapacity);
+        }
+        _segment = 0;
+    }
+
+    public ByteBuffer buffer()
+    {
+        int pos = _out.position();
+        _out.position(_segment);
+        ByteBuffer slice = _out.slice();
+        slice.limit(pos - _segment);
+        _out.position(pos);
+        return slice;
+    }
+
+    public int position()
+    {
+        return _out.position();
+    }
+
+    public ByteBuffer underlyingBuffer()
+    {
+        return _out;
+    }
+
+    private void grow(int size)
+    {
+        ByteBuffer old = _out;
+        int capacity = old.capacity();
+        _out = ByteBuffer.allocate(Math.max(Math.max(capacity + size, 2*capacity), _initialCapacity));
+        old.flip();
+        _out.put(old);
+    }
+
+    protected void doPut(byte b)
+    {
+        try
+        {
+            _out.put(b);
+        }
+        catch (BufferOverflowException e)
+        {
+            grow(1);
+            _out.put(b);
+        }
+    }
+
+    protected void doPut(ByteBuffer src)
+    {
+        try
+        {
+            _out.put(src);
+        }
+        catch (BufferOverflowException e)
+        {
+            grow(src.remaining());
+            _out.put(src);
+        }
+    }
+
+    protected void put(byte[] bytes)
+    {
+        try
+        {
+            _out.put(bytes);
+        }
+        catch (BufferOverflowException e)
+        {
+            grow(bytes.length);
+            _out.put(bytes);
+        }
+    }
+
+    public void writeUint8(short b)
+    {
+        assert b < 0x100;
+
+        try
+        {
+            _out.put((byte) b);
+        }
+        catch (BufferOverflowException e)
+        {
+            grow(1);
+            _out.put((byte) b);
+        }
+    }
+
+    public void writeUint16(int s)
+    {
+        assert s < 0x10000;
+
+        try
+        {
+            _out.putShort((short) s);
+        }
+        catch (BufferOverflowException e)
+        {
+            grow(2);
+            _out.putShort((short) s);
+        }
+    }
+
+    public void writeUint32(long i)
+    {
+        assert i < 0x100000000L;
+
+        try
+        {
+            _out.putInt((int) i);
+        }
+        catch (BufferOverflowException e)
+        {
+            grow(4);
+            _out.putInt((int) i);
+        }
+    }
+
+    public void writeUint64(long l)
+    {
+        try
+        {
+            _out.putLong(l);
+        }
+        catch (BufferOverflowException e)
+        {
+            grow(8);
+            _out.putLong(l);
+        }
+    }
+
+    public int beginSize8()
+    {
+        int pos = _out.position();
+        try
+        {
+            _out.put((byte) 0);
+        }
+        catch (BufferOverflowException e)
+        {
+            grow(1);
+            _out.put((byte) 0);
+        }
+        return pos;
+    }
+
+    public void endSize8(int pos)
+    {
+        int cur = _out.position();
+        _out.put(pos, (byte) (cur - pos - 1));
+    }
+
+    public int beginSize16()
+    {
+        int pos = _out.position();
+        try
+        {
+            _out.putShort((short) 0);
+        }
+        catch (BufferOverflowException e)
+        {
+            grow(2);
+            _out.putShort((short) 0);
+        }
+        return pos;
+    }
+
+    public void endSize16(int pos)
+    {
+        int cur = _out.position();
+        _out.putShort(pos, (short) (cur - pos - 2));
+    }
+
+    public int beginSize32()
+    {
+        int pos = _out.position();
+        try
+        {
+            _out.putInt(0);
+        }
+        catch (BufferOverflowException e)
+        {
+            grow(4);
+            _out.putInt(0);
+        }
+        return pos;
+
+    }
+
+    public void endSize32(int pos)
+    {
+        int cur = _out.position();
+        _out.putInt(pos, (cur - pos - 4));
+
+    }
+
+	public void writeDouble(double aDouble)
+	{
+		try
+		{
+			_out.putDouble(aDouble);
+		}
+        catch(BufferOverflowException exception)
+		{
+			grow(8);
+			_out.putDouble(aDouble);
+		}
+	}
+
+	public void writeInt16(short aShort)
+	{
+		try 
+		{
+			_out.putShort(aShort);
+		}
+        catch(BufferOverflowException exception)
+		{
+			grow(2);
+			_out.putShort(aShort);
+		}
+	}
+
+	public void writeInt32(int anInt)
+	{
+		try
+		{
+			_out.putInt(anInt);
+		}
+        catch(BufferOverflowException exception)
+		{
+			grow(4);
+			_out.putInt(anInt);
+		}
+	}
+
+	public void writeInt64(long aLong)
+	{
+		try
+		{
+			_out.putLong(aLong);
+		}
+        catch(BufferOverflowException exception)
+		{
+			grow(8);
+			_out.putLong(aLong);
+		}
+	}
+      
+	public void writeInt8(byte aByte)
+	{
+		try 
+		{
+			_out.put(aByte);
+		}
+        catch(BufferOverflowException exception)
+		{
+			grow(1);
+			_out.put(aByte);
+		}
+	}	
+	
+	public void writeBin128(byte[] byteArray)
+	{
+		byteArray = (byteArray != null) ? byteArray : new byte [16];
+		
+		assert byteArray.length == 16;
+		
+		try 
+		{
+			_out.put(byteArray);
+		}
+        catch(BufferOverflowException exception)
+		{
+			grow(16);
+			_out.put(byteArray);
+		}
+	}
+
+    public void writeBin128(UUID id)
+	{
+        byte[] data = new byte[16];
+
+        long msb = id.getMostSignificantBits();
+        long lsb = id.getLeastSignificantBits();
+
+        assert data.length == 16;
+        for (int i=7; i>=0; i--)
+        {
+            data[i] = (byte)(msb & 0xff);
+            msb = msb >> 8;
+        }
+
+        for (int i=15; i>=8; i--)
+        {
+            data[i] = (byte)(lsb & 0xff);
+            lsb = (lsb >> 8);
+        }
+        writeBin128(data);
+    }
+
+	public void writeFloat(float aFloat)
+	{
+		try 
+		{
+			_out.putFloat(aFloat);
+		}
+        catch(BufferOverflowException exception)
+		{
+			grow(4);
+			_out.putFloat(aFloat);
+		}
+	}
+
+}
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSession.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSession.java
index 223de4f..6720442 100644
--- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSession.java
+++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSession.java
@@ -56,6 +56,7 @@
 import org.apache.qpid.server.TransactionTimeoutHelper.CloseAction;
 import org.apache.qpid.server.connection.SessionPrincipal;
 import org.apache.qpid.server.consumer.ConsumerImpl;
+import org.apache.qpid.server.consumer.ConsumerTarget;
 import org.apache.qpid.server.logging.LogMessage;
 import org.apache.qpid.server.logging.LogSubject;
 import org.apache.qpid.server.logging.messages.ChannelMessages;
@@ -74,7 +75,7 @@
 import org.apache.qpid.server.security.AuthorizationHolder;
 import org.apache.qpid.server.store.MessageStore;
 import org.apache.qpid.server.store.StoreException;
-import org.apache.qpid.server.store.StoreFuture;
+import org.apache.qpid.server.util.FutureResult;
 import org.apache.qpid.server.store.StoredMessage;
 import org.apache.qpid.server.store.TransactionLogResource;
 import org.apache.qpid.server.txn.AlreadyKnownDtxException;
@@ -136,6 +137,7 @@
     private org.apache.qpid.server.model.Session<?> _modelObject;
     private long _blockTime;
     private long _blockingTimeout;
+    private boolean _wireBlockingState;
 
     public static interface MessageDispositionChangeListener
     {
@@ -188,7 +190,7 @@
             @Override
             public void doTimeoutAction(String reason)
             {
-                getConnectionModel().closeSession(ServerSession.this, AMQConstant.RESOURCE_ERROR, reason);
+                getConnectionModel().closeSessionAsync(ServerSession.this, AMQConstant.RESOURCE_ERROR, reason);
             }
         }, getVirtualHost());
 
@@ -207,10 +209,6 @@
             if (state == State.OPEN)
             {
                 getVirtualHost().getEventLogger().message(ChannelMessages.CREATE());
-                if(_blocking.get())
-                {
-                    invokeBlock();
-                }
             }
         }
         else
@@ -244,6 +242,17 @@
         invoke(new MessageStop(""));
     }
 
+    private void invokeUnblock()
+    {
+        MessageFlow mf = new MessageFlow();
+        mf.setUnit(MessageCreditUnit.MESSAGE);
+        mf.setDestination("");
+        _outstandingCredit.set(Integer.MAX_VALUE);
+        mf.setValue(Integer.MAX_VALUE);
+        invoke(mf);
+    }
+
+
     @Override
     protected boolean isFull(int id)
     {
@@ -823,12 +832,11 @@
 
                 if(_blocking.compareAndSet(false,true))
                 {
+                    getVirtualHost().getEventLogger().message(_logSubject, ChannelMessages.FLOW_ENFORCED(name));
                     if(getState() == State.OPEN)
                     {
-                        invokeBlock();
+                        getConnection().notifyWork();
                     }
-                    _blockTime = System.currentTimeMillis();
-                    getVirtualHost().getEventLogger().message(_logSubject, ChannelMessages.FLOW_ENFORCED(name));
                 }
 
 
@@ -852,28 +860,30 @@
         {
             if(_blocking.compareAndSet(true,false) && !isClosing())
             {
-                _blockTime = 0l;
                 getVirtualHost().getEventLogger().message(_logSubject, ChannelMessages.FLOW_REMOVED());
-                MessageFlow mf = new MessageFlow();
-                mf.setUnit(MessageCreditUnit.MESSAGE);
-                mf.setDestination("");
-                _outstandingCredit.set(Integer.MAX_VALUE);
-                mf.setValue(Integer.MAX_VALUE);
-                invoke(mf);
-
-
+                getConnection().notifyWork();
             }
         }
     }
 
+
     boolean blockingTimeoutExceeded()
     {
         long blockTime = _blockTime;
-        boolean b = _blocking.get() && blockTime != 0 && (System.currentTimeMillis() - blockTime) > _blockingTimeout;
+        boolean b = _wireBlockingState && blockTime != 0 && (System.currentTimeMillis() - blockTime) > _blockingTimeout;
         return b;
     }
 
     @Override
+    public void transportStateChanged()
+    {
+        for(ConsumerTarget_0_10 consumerTarget : getSubscriptions())
+        {
+            consumerTarget.transportStateChanged();
+        }
+    }
+
+    @Override
     public Object getConnectionReference()
     {
         return getConnection().getReference();
@@ -1002,17 +1012,17 @@
         return _unfinishedCommandsQueue.isEmpty() ? null : _unfinishedCommandsQueue.getLast();
     }
 
-    public void recordFuture(final StoreFuture future, final ServerTransaction.Action action)
+    public void recordFuture(final FutureResult future, final ServerTransaction.Action action)
     {
         _unfinishedCommandsQueue.add(new AsyncCommand(future, action));
     }
 
     private static class AsyncCommand
     {
-        private final StoreFuture _future;
+        private final FutureResult _future;
         private ServerTransaction.Action _action;
 
-        public AsyncCommand(final StoreFuture future, final ServerTransaction.Action action)
+        public AsyncCommand(final FutureResult future, final ServerTransaction.Action action)
         {
             _future = future;
             _action = action;
@@ -1125,6 +1135,32 @@
         }
     }
 
+    @Override
+    public void processPending()
+    {
+        boolean desiredBlockingState = _blocking.get();
+        if (desiredBlockingState != _wireBlockingState)
+        {
+            _wireBlockingState = desiredBlockingState;
+
+            if (desiredBlockingState)
+            {
+                invokeBlock();
+            }
+            else
+            {
+                invokeUnblock();
+            }
+            _blockTime = desiredBlockingState ? System.currentTimeMillis() : 0;
+        }
+
+
+        for(ConsumerTarget target : getSubscriptions())
+        {
+            target.processPending();
+        }
+    }
+
 
     public final long getMaxUncommittedInMemorySize()
     {
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java
index 8632d04..dd634c3 100644
--- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java
+++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java
@@ -36,8 +36,10 @@
 import org.apache.qpid.common.AMQPFilterTypes;
 import org.apache.qpid.exchange.ExchangeDefaults;
 import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.server.protocol.ServerProtocolEngine;
 import org.apache.qpid.server.consumer.ConsumerImpl;
 import org.apache.qpid.server.exchange.ExchangeImpl;
+import org.apache.qpid.server.virtualhost.VirtualHostUnavailableException;
 import org.apache.qpid.server.filter.AMQInvalidArgumentException;
 import org.apache.qpid.server.filter.ArrivalTimeFilter;
 import org.apache.qpid.server.filter.FilterManager;
@@ -58,7 +60,7 @@
 import org.apache.qpid.server.queue.QueueArgumentsConverter;
 import org.apache.qpid.server.store.MessageStore;
 import org.apache.qpid.server.store.StoreException;
-import org.apache.qpid.server.store.StoreFuture;
+import org.apache.qpid.server.util.FutureResult;
 import org.apache.qpid.server.store.StoredMessage;
 import org.apache.qpid.server.txn.AlreadyKnownDtxException;
 import org.apache.qpid.server.txn.DtxNotSelectedException;
@@ -133,7 +135,7 @@
         serverSession.accept(method.getTransfers());
         if(!serverSession.isTransactional())
         {
-            serverSession.recordFuture(StoreFuture.IMMEDIATE_FUTURE,
+            serverSession.recordFuture(FutureResult.IMMEDIATE_FUTURE,
                                        new CommandProcessedAction(serverSession, method));
         }
     }
@@ -246,8 +248,8 @@
                 }
                 else
                 {
-
-                    FlowCreditManager_0_10 creditManager = new WindowCreditManager(0L,0L);
+                    ServerProtocolEngine serverProtocolEngine = getServerConnection(session).getProtocolEngine();
+                    FlowCreditManager_0_10 creditManager = new WindowCreditManager(0L,0L, serverProtocolEngine);
 
                     FilterManager filterManager = null;
                     try
@@ -421,58 +423,69 @@
                     new MessageTransferMessage(storeMessage, serverSession.getReference());
             MessageReference<MessageTransferMessage> reference = message.newReference();
 
-            final InstanceProperties instanceProperties = new InstanceProperties()
+            try
             {
-                @Override
-                public Object getProperty(final Property prop)
+                final InstanceProperties instanceProperties = new InstanceProperties()
                 {
-                    switch (prop)
+                    @Override
+                    public Object getProperty(final Property prop)
                     {
-                        case EXPIRATION:
-                            return message.getExpiration();
-                        case IMMEDIATE:
-                            return message.isImmediate();
-                        case MANDATORY:
-                            return (delvProps == null || !delvProps.getDiscardUnroutable())
-                                   && xfr.getAcceptMode() == MessageAcceptMode.EXPLICIT;
-                        case PERSISTENT:
-                            return message.isPersistent();
-                        case REDELIVERED:
-                            return delvProps.getRedelivered();
+                        switch (prop)
+                        {
+                            case EXPIRATION:
+                                return message.getExpiration();
+                            case IMMEDIATE:
+                                return message.isImmediate();
+                            case MANDATORY:
+                                return (delvProps == null || !delvProps.getDiscardUnroutable())
+                                       && xfr.getAcceptMode() == MessageAcceptMode.EXPLICIT;
+                            case PERSISTENT:
+                                return message.isPersistent();
+                            case REDELIVERED:
+                                return delvProps.getRedelivered();
+                        }
+                        return null;
                     }
-                    return null;
-                }
-            };
+                };
 
-            int enqueues = serverSession.enqueue(message, instanceProperties, destination);
+                int enqueues = serverSession.enqueue(message, instanceProperties, destination);
 
-            if (enqueues == 0)
-            {
-                if ((delvProps == null || !delvProps.getDiscardUnroutable())
-                    && xfr.getAcceptMode() == MessageAcceptMode.EXPLICIT)
+                if (enqueues == 0)
                 {
-                    RangeSet rejects = RangeSetFactory.createRangeSet();
-                    rejects.add(xfr.getId());
-                    MessageReject reject = new MessageReject(rejects, MessageRejectCode.UNROUTABLE, "Unroutable");
-                    ssn.invoke(reject);
+                    if ((delvProps == null || !delvProps.getDiscardUnroutable())
+                        && xfr.getAcceptMode() == MessageAcceptMode.EXPLICIT)
+                    {
+                        RangeSet rejects = RangeSetFactory.createRangeSet();
+                        rejects.add(xfr.getId());
+                        MessageReject reject = new MessageReject(rejects, MessageRejectCode.UNROUTABLE, "Unroutable");
+                        ssn.invoke(reject);
+                    }
+                    else
+                    {
+                        virtualHost.getEventLogger().message(ExchangeMessages.DISCARDMSG(destination.getName(),
+                                                                                         messageMetaData.getRoutingKey()));
+                    }
+                }
+
+                if (serverSession.isTransactional())
+                {
+                    serverSession.processed(xfr);
                 }
                 else
                 {
-                    virtualHost.getEventLogger().message(ExchangeMessages.DISCARDMSG(destination.getName(),
-                                                                                     messageMetaData.getRoutingKey()));
+                    serverSession.recordFuture(FutureResult.IMMEDIATE_FUTURE,
+                                               new CommandProcessedAction(serverSession, xfr));
                 }
             }
+            catch (VirtualHostUnavailableException e)
+            {
+                getServerConnection(serverSession).closeAsync(AMQConstant.CONNECTION_FORCED, e.getMessage());
+            }
+            finally
+            {
+                reference.release();
+            }
 
-            if (serverSession.isTransactional())
-            {
-                serverSession.processed(xfr);
-            }
-            else
-            {
-                serverSession.recordFuture(StoreFuture.IMMEDIATE_FUTURE,
-                                           new CommandProcessedAction(serverSession, xfr));
-            }
-            reference.release();
         }
     }
 
@@ -589,7 +602,7 @@
         {
             try
             {
-                ((ServerSession)session).endDtx(method.getXid(), method.getFail(), method.getSuspend());
+                ((ServerSession) session).endDtx(method.getXid(), method.getFail(), method.getSuspend());
             }
             catch (TimeoutDtxException e)
             {
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/WindowCreditManager.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/WindowCreditManager.java
index 8e48741..a7b08e3 100644
--- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/WindowCreditManager.java
+++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/WindowCreditManager.java
@@ -21,11 +21,14 @@
 package org.apache.qpid.server.protocol.v0_10;
 
 import org.apache.log4j.Logger;
+
+import org.apache.qpid.server.protocol.ServerProtocolEngine;
 import org.apache.qpid.server.flow.AbstractFlowCreditManager;
 
 public class WindowCreditManager extends AbstractFlowCreditManager implements FlowCreditManager_0_10
 {
     private static final Logger LOGGER = Logger.getLogger(WindowCreditManager.class);
+    private final ServerProtocolEngine _serverProtocolEngine;
 
     private volatile long _bytesCreditLimit;
     private volatile long _messageCreditLimit;
@@ -33,39 +36,22 @@
     private volatile long _bytesUsed;
     private volatile long _messageUsed;
 
-     public WindowCreditManager()
-     {
-         this(0L, 0L);
-     }
-
-    public WindowCreditManager(long bytesCreditLimit, long messageCreditLimit)
+    public WindowCreditManager(long bytesCreditLimit,
+                               long messageCreditLimit,
+                               ServerProtocolEngine serverProtocolEngine)
     {
+        _serverProtocolEngine = serverProtocolEngine;
         _bytesCreditLimit = bytesCreditLimit;
         _messageCreditLimit = messageCreditLimit;
         setSuspended(!hasCredit());
 
     }
 
-    public long getBytesCreditLimit()
-    {
-        return _bytesCreditLimit;
-    }
-
     public long getMessageCreditLimit()
     {
         return _messageCreditLimit;
     }
 
-    public synchronized void setCreditLimits(final long bytesCreditLimit, final long messageCreditLimit)
-    {
-        _bytesCreditLimit = bytesCreditLimit;
-        _messageCreditLimit = messageCreditLimit;
-
-        setSuspended(!hasCredit());
-
-    }
-
-
     public long getMessageCredit()
     {
          return _messageCreditLimit == -1L
@@ -121,12 +107,18 @@
     public synchronized boolean hasCredit()
     {
         return (_bytesCreditLimit < 0L || _bytesCreditLimit > _bytesUsed)
-                && (_messageCreditLimit < 0L || _messageCreditLimit > _messageUsed);
+                && (_messageCreditLimit < 0L || _messageCreditLimit > _messageUsed)
+                && !_serverProtocolEngine.isTransportBlockedForWriting();
     }
 
     public synchronized boolean useCreditForMessage(final long msgSize)
     {
-        if(_messageCreditLimit >= 0L)
+        if (_serverProtocolEngine.isTransportBlockedForWriting())
+        {
+            setSuspended(true);
+            return false;
+        }
+        else if(_messageCreditLimit >= 0L)
         {
             if(_messageUsed < _messageCreditLimit)
             {
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/test/java/org/apache/qpid/server/protocol/v0_10/WindowCreditManagerTest.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/test/java/org/apache/qpid/server/protocol/v0_10/WindowCreditManagerTest.java
index 1c4a694..b9f013d 100644
--- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/test/java/org/apache/qpid/server/protocol/v0_10/WindowCreditManagerTest.java
+++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/test/java/org/apache/qpid/server/protocol/v0_10/WindowCreditManagerTest.java
@@ -20,17 +20,25 @@
  */
 package org.apache.qpid.server.protocol.v0_10;
 
-import org.apache.qpid.server.protocol.v0_10.WindowCreditManager;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.apache.qpid.server.protocol.ServerProtocolEngine;
 import org.apache.qpid.test.utils.QpidTestCase;
 
 public class WindowCreditManagerTest extends QpidTestCase
 {
     private WindowCreditManager _creditManager;
+    private ServerProtocolEngine _protocolEngine;
 
     protected void setUp() throws Exception
     {
         super.setUp();
-        _creditManager = new WindowCreditManager();
+
+        _protocolEngine = mock(ServerProtocolEngine.class);
+        when(_protocolEngine.isTransportBlockedForWriting()).thenReturn(false);
+
+        _creditManager = new WindowCreditManager(0l, 0l, _protocolEngine);
     }
 
     /**
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/pom.xml b/qpid/java/broker-plugins/amqp-0-8-protocol/pom.xml
index 0c5d20a..e09a3ba 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/pom.xml
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/pom.xml
@@ -29,6 +29,10 @@
   <name>Qpid AMQP 0-8 Protocol Broker Plug-in</name>
   <description>AMQP 0-8, 0-9 and 0-9-1 protocol broker plug-in</description>
 
+  <properties>
+    <qpid.home>${basedir}/../</qpid.home> <!-- override for broker tests -->
+  </properties>
+
   <dependencies>
     <dependency>
       <groupId>org.apache.qpid</groupId>
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java
index 9afa7c3..2a1fbe6 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java
@@ -40,7 +40,6 @@
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.locks.Lock;
 
 import javax.security.auth.Subject;
 
@@ -66,8 +65,6 @@
 import org.apache.qpid.server.filter.Filterable;
 import org.apache.qpid.server.filter.MessageFilter;
 import org.apache.qpid.server.flow.FlowCreditManager;
-import org.apache.qpid.server.flow.MessageOnlyCreditManager;
-import org.apache.qpid.server.flow.Pre0_10CreditManager;
 import org.apache.qpid.server.logging.LogMessage;
 import org.apache.qpid.server.logging.LogSubject;
 import org.apache.qpid.server.logging.messages.ChannelMessages;
@@ -99,7 +96,6 @@
 import org.apache.qpid.server.queue.QueueArgumentsConverter;
 import org.apache.qpid.server.security.SecurityManager;
 import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.StoreFuture;
 import org.apache.qpid.server.store.StoredMessage;
 import org.apache.qpid.server.store.TransactionLogResource;
 import org.apache.qpid.server.txn.AsyncAutoCommitTransaction;
@@ -108,6 +104,7 @@
 import org.apache.qpid.server.txn.ServerTransaction;
 import org.apache.qpid.server.util.Action;
 import org.apache.qpid.server.util.ConnectionScopedRuntimeException;
+import org.apache.qpid.server.util.FutureResult;
 import org.apache.qpid.server.virtualhost.ExchangeExistsException;
 import org.apache.qpid.server.virtualhost.ExchangeIsAlternateException;
 import org.apache.qpid.server.virtualhost.QueueExistsException;
@@ -133,7 +130,8 @@
     private final int _channelId;
 
 
-    private final Pre0_10CreditManager _creditManager = new Pre0_10CreditManager(0l,0l);
+    private final Pre0_10CreditManager _creditManager;
+    private final FlowCreditManager _noAckCreditManager;
 
     /**
      * The delivery tag is unique per channel. This is pre-incremented before putting into the deliver frame so that
@@ -211,8 +209,13 @@
     private final List<StoredMessage<MessageMetaData>> _uncommittedMessages = new ArrayList<>();
     private long _maxUncommittedInMemorySize;
 
+    private boolean _wireBlockingState;
+
     public AMQChannel(AMQProtocolEngine connection, int channelId, final MessageStore messageStore)
     {
+        _creditManager = new Pre0_10CreditManager(0l,0l, connection);
+        _noAckCreditManager = new NoAckCreditManager(connection);
+
         _connection = connection;
         _channelId = channelId;
 
@@ -699,7 +702,7 @@
 
         if(arguments != null && Boolean.TRUE.equals(arguments.get(AMQPFilterTypes.NO_CONSUME.getValue())))
         {
-            target = ConsumerTarget_0_8.createBrowserTarget(this, tag, arguments, _creditManager);
+            target = ConsumerTarget_0_8.createBrowserTarget(this, tag, arguments, _noAckCreditManager);
         }
         else if(acks)
         {
@@ -709,7 +712,7 @@
         }
         else
         {
-            target = ConsumerTarget_0_8.createNoAckTarget(this, tag, arguments, _creditManager);
+            target = ConsumerTarget_0_8.createNoAckTarget(this, tag, arguments, _noAckCreditManager);
             options.add(ConsumerImpl.Option.ACQUIRES);
             options.add(ConsumerImpl.Option.SEES_REQUEUES);
         }
@@ -1274,7 +1277,8 @@
 
         // stop all subscriptions
         _rollingBack = true;
-        boolean requiresSuspend = _suspended.compareAndSet(false,true);
+        boolean requiresSuspend = _suspended.compareAndSet(false,true);  // TODO This is probably superfluous owing to the
+        // message assignment suspended logic in NBC.
 
         // ensure all subscriptions have seen the change to the channel state
         for(ConsumerTarget_0_8 sub : _tag2SubscriptionTargetMap.values())
@@ -1653,12 +1657,14 @@
     {
         if(_blockingEntities.add(this))
         {
+
             if(_blocking.compareAndSet(false,true))
             {
                 getVirtualHost().getEventLogger().message(_logSubject,
                                                           ChannelMessages.FLOW_ENFORCED("** All Queues **"));
-                flow(false);
-                _blockTime = System.currentTimeMillis();
+
+
+                getConnection().notifyWork();
             }
         }
     }
@@ -1670,12 +1676,12 @@
             if(_blockingEntities.isEmpty() && _blocking.compareAndSet(true,false))
             {
                 getVirtualHost().getEventLogger().message(_logSubject, ChannelMessages.FLOW_REMOVED());
-
-                flow(true);
+                getConnection().notifyWork();
             }
         }
     }
 
+
     public synchronized void block(AMQQueue queue)
     {
         if(_blockingEntities.add(queue))
@@ -1684,8 +1690,7 @@
             if(_blocking.compareAndSet(false,true))
             {
                 getVirtualHost().getEventLogger().message(_logSubject, ChannelMessages.FLOW_ENFORCED(queue.getName()));
-                flow(false);
-                _blockTime = System.currentTimeMillis();
+                getConnection().notifyWork();
 
             }
         }
@@ -1698,12 +1703,19 @@
             if(_blockingEntities.isEmpty() && _blocking.compareAndSet(true,false) && !isClosing())
             {
                 getVirtualHost().getEventLogger().message(_logSubject, ChannelMessages.FLOW_REMOVED());
-                flow(true);
+                getConnection().notifyWork();
             }
         }
     }
 
     @Override
+    public void transportStateChanged()
+    {
+        _creditManager.restoreCredit(0, 0);
+        _noAckCreditManager.restoreCredit(0, 0);
+    }
+
+    @Override
     public Object getConnectionReference()
     {
         return getConnection().getReference();
@@ -1743,16 +1755,7 @@
      */
     private void closeConnection(String reason) throws AMQException
     {
-        Lock receivedLock = _connection.getReceivedLock();
-        receivedLock.lock();
-        try
-        {
-            _connection.close(AMQConstant.RESOURCE_ERROR, reason);
-        }
-        finally
-        {
-            receivedLock.unlock();
-        }
+        _connection.closeAsync(AMQConstant.RESOURCE_ERROR, reason);
     }
 
     public void deadLetter(long deliveryTag)
@@ -1815,7 +1818,7 @@
         }
     }
 
-    public void recordFuture(final StoreFuture future, final ServerTransaction.Action action)
+    public void recordFuture(final FutureResult future, final ServerTransaction.Action action)
     {
         _unfinishedCommandsQueue.add(new AsyncCommand(future, action));
     }
@@ -1841,10 +1844,10 @@
 
     private static class AsyncCommand
     {
-        private final StoreFuture _future;
+        private final FutureResult _future;
         private ServerTransaction.Action _action;
 
-        public AsyncCommand(final StoreFuture future, final ServerTransaction.Action action)
+        public AsyncCommand(final FutureResult future, final ServerTransaction.Action action)
         {
             _future = future;
             _action = action;
@@ -2305,7 +2308,7 @@
     private boolean blockingTimeoutExceeded()
     {
 
-        return _blocking.get() && (System.currentTimeMillis() - _blockTime) > _blockingTimeout;
+        return _wireBlockingState && (System.currentTimeMillis() - _blockTime) > _blockingTimeout;
     }
 
     @Override
@@ -3639,4 +3642,22 @@
             }
         }
     }
+
+    @Override
+    public void processPending()
+    {
+
+        boolean desiredBlockingState = _blocking.get();
+        if (desiredBlockingState != _wireBlockingState)
+        {
+            _wireBlockingState = desiredBlockingState;
+            flow(!desiredBlockingState);
+            _blockTime = desiredBlockingState ? System.currentTimeMillis() : 0;
+        }
+
+        for(ConsumerTarget target : _tag2SubscriptionTargetMap.values())
+        {
+            target.processPending();
+        }
+    }
 }
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngine.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngine.java
index cb145aa..d7b5b00 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngine.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngine.java
@@ -36,13 +36,14 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Queue;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.atomic.AtomicReference;
 
 import javax.security.auth.Subject;
 import javax.security.sasl.SaslException;
@@ -58,7 +59,7 @@
 import org.apache.qpid.framing.*;
 import org.apache.qpid.properties.ConnectionStartProperties;
 import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.protocol.ServerProtocolEngine;
+import org.apache.qpid.server.protocol.ServerProtocolEngine;
 import org.apache.qpid.server.configuration.BrokerProperties;
 import org.apache.qpid.server.connection.ConnectionPrincipal;
 import org.apache.qpid.server.consumer.ConsumerImpl;
@@ -69,6 +70,7 @@
 import org.apache.qpid.server.message.InstanceProperties;
 import org.apache.qpid.server.message.ServerMessage;
 import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.Consumer;
 import org.apache.qpid.server.model.Port;
 import org.apache.qpid.server.model.State;
 import org.apache.qpid.server.model.Transport;
@@ -85,7 +87,7 @@
 import org.apache.qpid.server.util.ConnectionScopedRuntimeException;
 import org.apache.qpid.server.util.ServerScopedRuntimeException;
 import org.apache.qpid.server.virtualhost.VirtualHostImpl;
-import org.apache.qpid.transport.Sender;
+import org.apache.qpid.transport.ByteBufferSender;
 import org.apache.qpid.transport.SenderClosedException;
 import org.apache.qpid.transport.SenderException;
 import org.apache.qpid.transport.TransportException;
@@ -96,6 +98,9 @@
                                           AMQConnectionModel<AMQProtocolEngine, AMQChannel>,
                                           ServerMethodProcessor<ServerChannelMethodProcessor>
 {
+
+
+
     enum ConnectionState
     {
         INIT,
@@ -117,6 +122,8 @@
     private static final long AWAIT_CLOSED_TIMEOUT = 60000;
     private final AmqpPort<?> _port;
     private final long _creationTime;
+    private final AtomicBoolean _stateChanged = new AtomicBoolean();
+    private final AtomicReference<Action<ServerProtocolEngine>> _workListener = new AtomicReference<>();
 
     private AMQShortString _contextKey;
 
@@ -139,11 +146,8 @@
      * The channels that the latest call to {@link #received(ByteBuffer)} applied to.
      * Used so we know which channels we need to call {@link AMQChannel#receivedComplete()}
      * on after handling the frames.
-     *
-     * Thread-safety: guarded by {@link #_receivedLock}.
      */
-    private final Set<AMQChannel> _channelsForCurrentMessage =
-            new HashSet<>();
+    private final Set<AMQChannel> _channelsForCurrentMessage = new HashSet<>();
 
     private AMQDecoder _decoder;
 
@@ -157,9 +161,12 @@
     /* AMQP Version for this session */
     private ProtocolVersion _protocolVersion = ProtocolVersion.getLatestSupportedVersion();
     private final MethodRegistry _methodRegistry = new MethodRegistry(_protocolVersion);
-    private final List<Action<? super AMQProtocolEngine>> _taskList =
+    private final List<Action<? super AMQProtocolEngine>> _connectionCloseTaskList =
             new CopyOnWriteArrayList<>();
 
+    private final Queue<Action<? super AMQProtocolEngine>> _asyncTaskList =
+            new ConcurrentLinkedQueue<>();
+
     private Map<Integer, Long> _closingChannelsList = new ConcurrentHashMap<>();
     private ProtocolOutputConverter _protocolOutputConverter;
     private final Subject _authorizedSubject = new Subject();
@@ -179,13 +186,12 @@
     private final StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived;
 
     private NetworkConnection _network;
-    private Sender<ByteBuffer> _sender;
+    private ByteBufferSender _sender;
 
     private volatile boolean _deferFlush;
-    private long _lastReceivedTime;
+    private long _lastReceivedTime = System.currentTimeMillis();  // TODO consider if this is what we want?
     private boolean _blocking;
 
-    private final ReentrantLock _receivedLock;
     private AtomicLong _lastWriteTime = new AtomicLong(System.currentTimeMillis());
     private final Broker<?> _broker;
     private final Transport _transport;
@@ -200,6 +206,34 @@
     private int _currentMethodId;
     private int _binaryDataLimit;
     private long _maxMessageSize;
+    private volatile boolean _transportBlockedForWriting;
+
+    private final AtomicReference<Thread> _messageAssignmentSuspended = new AtomicReference<>();
+
+
+    @Override
+    public boolean isMessageAssignmentSuspended()
+    {
+        Thread lock = _messageAssignmentSuspended.get();
+        return lock != null && _messageAssignmentSuspended.get() != Thread.currentThread();
+    }
+
+    @Override
+    public void setMessageAssignmentSuspended(final boolean messageAssignmentSuspended)
+    {
+        _messageAssignmentSuspended.set(messageAssignmentSuspended ? Thread.currentThread() : null);
+        if(!messageAssignmentSuspended)
+        {
+            for(AMQSessionModel<?,?> session : getSessionModels())
+            {
+                for(Consumer<?> consumer : session.getConsumers())
+                {
+                    ((ConsumerImpl)consumer).getTarget().notifyCurrentState();
+                }
+            }
+        }
+    }
+
 
     public AMQProtocolEngine(Broker<?> broker,
                              final NetworkConnection network,
@@ -211,7 +245,6 @@
         _port = port;
         _transport = transport;
         _maxNoOfChannels = broker.getConnection_sessionCountLimit();
-        _receivedLock = new ReentrantLock();
         _decoder = new BrokerDecoder(this);
         _connectionID = connectionId;
         _logSubject = new ConnectionLogSubject(this);
@@ -262,12 +295,28 @@
         return _authorizedSubject;
     }
 
+    @Override
+    public boolean isTransportBlockedForWriting()
+    {
+        return _transportBlockedForWriting;
+    }
+
+    @Override
+    public void setTransportBlockedForWriting(final boolean blocked)
+    {
+        _transportBlockedForWriting = blocked;
+        for(AMQChannel channel : _channelMap.values())
+        {
+            channel.transportStateChanged();
+        }
+    }
+
     public void setNetworkConnection(NetworkConnection network)
     {
         setNetworkConnection(network, network.getSender());
     }
 
-    public void setNetworkConnection(NetworkConnection network, Sender<ByteBuffer> sender)
+    public void setNetworkConnection(NetworkConnection network, ByteBufferSender sender)
     {
         _network = network;
         _sender = sender;
@@ -294,10 +343,6 @@
         return _closing.get();
     }
 
-    public synchronized void flushBatched()
-    {
-        _sender.flush();
-    }
 
 
     public ClientDeliveryMethod createDeliveryMethod(int channelId)
@@ -314,9 +359,9 @@
             {
 
                 final long arrivalTime = System.currentTimeMillis();
-                if(!_authenticated &&
-                   (arrivalTime - _creationTime) > _port.getContextValue(Long.class,
-                                                                         Port.CONNECTION_MAXIMUM_AUTHENTICATION_DELAY))
+                if (!_authenticated &&
+                    (arrivalTime - _creationTime) > _port.getContextValue(Long.class,
+                                                                          Port.CONNECTION_MAXIMUM_AUTHENTICATION_DELAY))
                 {
                     _logger.warn("Connection has taken more than "
                                  + _port.getContextValue(Long.class, Port.CONNECTION_MAXIMUM_AUTHENTICATION_DELAY)
@@ -328,7 +373,6 @@
                 _lastIoTime = arrivalTime;
                 _readBytes += msg.remaining();
 
-                _receivedLock.lock();
                 try
                 {
                     _decoder.decodeBuffer(msg);
@@ -371,7 +415,7 @@
                 }
                 catch (StoreException e)
                 {
-                    if(_virtualHost.getState() == State.ACTIVE)
+                    if (_virtualHost.getState() == State.ACTIVE)
                     {
                         throw e;
                     }
@@ -380,10 +424,6 @@
                         _logger.error("Store Exception ignored as virtual host no longer active", e);
                     }
                 }
-                finally
-                {
-                    _receivedLock.unlock();
-                }
                 return null;
             }
         });
@@ -484,64 +524,22 @@
             writeFrame(responseBody.generateFrame(0));
             _state = ConnectionState.AWAIT_START_OK;
 
+            _sender.flush();
+
         }
         catch (AMQException e)
         {
             _logger.info("Received unsupported protocol initiation for protocol version: " + getProtocolVersion());
 
             writeFrame(new ProtocolInitiation(ProtocolVersion.getLatestSupportedVersion()));
+            _sender.flush();
         }
     }
 
 
     private final byte[] _reusableBytes = new byte[REUSABLE_BYTE_BUFFER_CAPACITY];
-    private final ByteBuffer _reusableByteBuffer = ByteBuffer.wrap(_reusableBytes);
     private final BytesDataOutput _reusableDataOutput = new BytesDataOutput(_reusableBytes);
 
-    private ByteBuffer asByteBuffer(AMQDataBlock block)
-    {
-        final int size = (int) block.getSize();
-
-        final byte[] data;
-
-
-        if(size > REUSABLE_BYTE_BUFFER_CAPACITY)
-        {
-            data= new byte[size];
-        }
-        else
-        {
-
-            data = _reusableBytes;
-        }
-        _reusableDataOutput.setBuffer(data);
-
-        try
-        {
-            block.writePayload(_reusableDataOutput);
-        }
-        catch (IOException e)
-        {
-            throw new ServerScopedRuntimeException(e);
-        }
-
-        final ByteBuffer buf;
-
-        if(size <= REUSABLE_BYTE_BUFFER_CAPACITY)
-        {
-            buf = _reusableByteBuffer;
-            buf.position(0);
-        }
-        else
-        {
-            buf = ByteBuffer.wrap(data);
-        }
-        buf.limit(_reusableDataOutput.length());
-
-        return buf;
-    }
-
-
     /**
      * Convenience method that writes a frame to the protocol session. Equivalent to calling
      * getProtocolSession().write().
@@ -550,16 +548,21 @@
      */
     public synchronized void writeFrame(AMQDataBlock frame)
     {
-
-        final ByteBuffer buf = asByteBuffer(frame);
-        _writtenBytes += buf.remaining();
-
         if(_logger.isDebugEnabled())
         {
             _logger.debug("SEND: " + frame);
         }
 
-        _sender.send(buf);
+        try
+        {
+            _writtenBytes += frame.writePayload(_sender);
+        }
+        catch (IOException e)
+        {
+            throw new ServerScopedRuntimeException(e);
+        }
+
+
         final long time = System.currentTimeMillis();
         _lastIoTime = time;
         _lastWriteTime.set(time);
@@ -796,14 +799,13 @@
             if(_closing.compareAndSet(false,true))
             {
                 // force sync of outstanding async work
-                _receivedLock.lock();
                 try
                 {
                     receivedComplete();
                 }
                 finally
                 {
-                    _receivedLock.unlock();
+
                     finishClose(connectionDropped);
                 }
 
@@ -845,7 +847,7 @@
             {
                 try
                 {
-                    for (Action<? super AMQProtocolEngine> task : _taskList)
+                    for (Action<? super AMQProtocolEngine> task : _connectionCloseTaskList)
                     {
                         task.performAction(this);
                     }
@@ -867,17 +869,12 @@
     {
         synchronized(this)
         {
-            final boolean lockHeld = _receivedLock.isHeldByCurrentThread();
             final long endTime = System.currentTimeMillis() + AWAIT_CLOSED_TIMEOUT;
 
             while(!_closed && endTime > System.currentTimeMillis())
             {
                 try
                 {
-                    if(lockHeld)
-                    {
-                        _receivedLock.unlock();
-                    }
                     wait(1000);
                 }
                 catch (InterruptedException e)
@@ -885,13 +882,6 @@
                     Thread.currentThread().interrupt();
                     break;
                 }
-                finally
-                {
-                    if(lockHeld)
-                    {
-                        _receivedLock.lock();
-                    }
-                }
             }
 
             if (!_closed)
@@ -1088,12 +1078,12 @@
 
     public void addDeleteTask(Action<? super AMQProtocolEngine> task)
     {
-        _taskList.add(task);
+        _connectionCloseTaskList.add(task);
     }
 
     public void removeDeleteTask(Action<? super AMQProtocolEngine> task)
     {
-        _taskList.remove(task);
+        _connectionCloseTaskList.remove(task);
     }
 
     public ProtocolOutputConverter getProtocolOutputConverter()
@@ -1171,6 +1161,11 @@
         }
     }
 
+    @Override
+    public void encryptedTransport()
+    {
+    }
+
     public void readerIdle()
     {
         Subject.doAs(_authorizedSubject, new PrivilegedAction<Object>()
@@ -1323,26 +1318,50 @@
         return String.valueOf(getRemoteAddress());
     }
 
-    public void closeSession(AMQChannel session, AMQConstant cause, String message)
+    public void closeSessionAsync(final AMQChannel session, final AMQConstant cause, final String message)
     {
-        int channelId = session.getChannelId();
-        closeChannel(channelId, cause, message);
+        addAsyncTask(new Action<AMQProtocolEngine>()
+        {
 
-        MethodRegistry methodRegistry = getMethodRegistry();
-        ChannelCloseBody responseBody =
-                methodRegistry.createChannelCloseBody(
-                        cause.getCode(),
-                        AMQShortString.validValueOf(message),
-                        0, 0);
+            @Override
+            public void performAction(final AMQProtocolEngine object)
+            {
+                int channelId = session.getChannelId();
+                closeChannel(channelId, cause, message);
 
-        writeFrame(responseBody.generateFrame(channelId));
+                MethodRegistry methodRegistry = getMethodRegistry();
+                ChannelCloseBody responseBody =
+                        methodRegistry.createChannelCloseBody(
+                                cause.getCode(),
+                                AMQShortString.validValueOf(message),
+                                0, 0);
+
+                writeFrame(responseBody.generateFrame(channelId));
+            }
+        });
+
     }
 
-    public void close(AMQConstant cause, String message)
+    public void closeAsync(final AMQConstant cause, final String message)
     {
-        closeConnection(0, new AMQConnectionException(cause, message, 0, 0,
-                                                      getMethodRegistry(),
-		                                              null));
+        Action<AMQProtocolEngine> action = new Action<AMQProtocolEngine>()
+        {
+            @Override
+            public void performAction(final AMQProtocolEngine object)
+            {
+                closeConnection(0, new AMQConnectionException(cause, message, 0, 0,
+                                                              getMethodRegistry(),
+                                                              null));
+
+            }
+        };
+        addAsyncTask(action);
+    }
+
+    private void addAsyncTask(final Action<AMQProtocolEngine> action)
+    {
+        _asyncTaskList.add(action);
+        notifyWork();
     }
 
     public void block()
@@ -1922,11 +1941,6 @@
         return _reference;
     }
 
-    public Lock getReceivedLock()
-    {
-        return _receivedLock;
-    }
-
     @Override
     public long getLastReadTime()
     {
@@ -2045,4 +2059,51 @@
         return _closing.get();
     }
 
+    @Override
+    public void processPending()
+    {
+
+
+        while(_asyncTaskList.peek() != null)
+        {
+            Action<? super AMQProtocolEngine> asyncAction = _asyncTaskList.poll();
+            asyncAction.performAction(this);
+        }
+
+        for (AMQSessionModel session : getSessionModels())
+        {
+            session.processPending();
+        }
+    }
+
+    @Override
+    public boolean hasWork()
+    {
+        return _stateChanged.get();
+    }
+
+    @Override
+    public void notifyWork()
+    {
+        _stateChanged.set(true);
+
+        final Action<ServerProtocolEngine> listener = _workListener.get();
+        if(listener != null)
+        {
+
+            listener.performAction(this);
+        }
+    }
+
+    @Override
+    public void clearWork()
+    {
+        _stateChanged.set(false);
+    }
+
+    @Override
+    public void setWorkListener(final Action<ServerProtocolEngine> listener)
+    {
+        _workListener.set(listener);
+    }
 }
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ConsumerTarget_0_8.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ConsumerTarget_0_8.java
index 43982db..a2113de 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ConsumerTarget_0_8.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ConsumerTarget_0_8.java
@@ -75,6 +75,7 @@
     private final AtomicLong _unacknowledgedCount = new AtomicLong(0);
     private final AtomicLong _unacknowledgedBytes = new AtomicLong(0);
     private final List<ConsumerImpl> _consumers = new CopyOnWriteArrayList<>();
+    private final AtomicBoolean _needToClose = new AtomicBoolean();
 
 
     public static ConsumerTarget_0_8 createBrowserTarget(AMQChannel channel,
@@ -99,6 +100,7 @@
         return _consumers;
     }
 
+
     static final class BrowserConsumer extends ConsumerTarget_0_8
     {
         public BrowserConsumer(AMQChannel channel,
@@ -123,7 +125,7 @@
          * @throws org.apache.qpid.AMQException
          */
         @Override
-        public long send(final ConsumerImpl consumer, MessageInstance entry, boolean batch)
+        public void doSend(final ConsumerImpl consumer, MessageInstance entry, boolean batch)
         {
             // We don't decrement the reference here as we don't want to consume the message
             // but we do want to send it to the client.
@@ -131,17 +133,11 @@
             synchronized (getChannel())
             {
                 long deliveryTag = getChannel().getNextDeliveryTag();
-                return sendToClient(consumer, entry.getMessage(), entry.getInstanceProperties(), deliveryTag);
+                sendToClient(consumer, entry.getMessage(), entry.getInstanceProperties(), deliveryTag);
             }
 
         }
 
-        @Override
-        public boolean allocateCredit(ServerMessage msg)
-        {
-            return true;
-        }
-
     }
 
     public static ConsumerTarget_0_8 createNoAckTarget(AMQChannel channel,
@@ -184,7 +180,7 @@
          * @param batch
          */
         @Override
-        public long send(final ConsumerImpl consumer, MessageInstance entry, boolean batch)
+        public void doSend(final ConsumerImpl consumer, MessageInstance entry, boolean batch)
         {
             // if we do not need to wait for client acknowledgements
             // we can decrement the reference count immediately.
@@ -211,16 +207,9 @@
 
             }
             ref.release();
-            return size;
 
         }
 
-        @Override
-        public boolean allocateCredit(ServerMessage msg)
-        {
-            return true;
-        }
-
         private static final ServerTransaction.Action NOOP =
                 new ServerTransaction.Action()
                 {
@@ -250,11 +239,6 @@
             super(channel, consumerTag, filters, creditManager, deliveryMethod, recordMethod);
         }
 
-        public boolean allocateCredit(ServerMessage msg)
-        {
-            return getCreditManager().useCreditForMessage(msg.getSize());
-        }
-
     }
 
 
@@ -295,9 +279,10 @@
          * @param batch
          */
         @Override
-        public long send(final ConsumerImpl consumer, MessageInstance entry, boolean batch)
+        public void doSend(final ConsumerImpl consumer, MessageInstance entry, boolean batch)
         {
 
+            // put queue entry on a list and then notify the connection to read list.
 
             synchronized (getChannel())
             {
@@ -309,12 +294,15 @@
                 entry.addStateChangeListener(getReleasedStateChangeListener());
                 long size = sendToClient(consumer, entry.getMessage(), entry.getInstanceProperties(), deliveryTag);
                 entry.incrementDeliveryCount();
-                return size;
             }
+
+
         }
 
 
 
+
+
     }
 
 
@@ -399,7 +387,8 @@
         return subscriber + "]";
     }
 
-    public boolean isSuspended()
+    @Override
+    public boolean doIsSuspended()
     {
         return getState()!=State.ACTIVE || _channel.isSuspended() || _deleted.get() || _channel.getConnectionModel().isStopped();
     }
@@ -525,6 +514,16 @@
     {
         if (isAutoClose())
         {
+            _needToClose.set(true);
+            getChannel().getConnection().notifyWork();
+        }
+    }
+
+    @Override
+    protected void processClosed()
+    {
+        if (_needToClose.get() && getState() != State.CLOSED)
+        {
             close();
             confirmAutoClose();
         }
@@ -533,8 +532,6 @@
     public void flushBatched()
     {
         _channel.getConnection().setDeferFlush(false);
-
-        _channel.getConnection().flushBatched();
     }
 
     protected void addUnacknowledgedMessage(MessageInstance entry)
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/flow/MessageOnlyCreditManager.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageOnlyCreditManager.java
similarity index 86%
rename from qpid/java/broker-core/src/main/java/org/apache/qpid/server/flow/MessageOnlyCreditManager.java
rename to qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageOnlyCreditManager.java
index 1817e8a..af54c91 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/flow/MessageOnlyCreditManager.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageOnlyCreditManager.java
@@ -18,10 +18,13 @@
 * under the License.
 *
 */
-package org.apache.qpid.server.flow;
+package org.apache.qpid.server.protocol.v0_8;
 
 import java.util.concurrent.atomic.AtomicLong;
 
+import org.apache.qpid.server.flow.AbstractFlowCreditManager;
+import org.apache.qpid.server.flow.FlowCreditManager;
+
 public class MessageOnlyCreditManager extends AbstractFlowCreditManager implements FlowCreditManager
 {
     private final AtomicLong _messageCredit;
@@ -31,16 +34,6 @@
         _messageCredit = new AtomicLong(initialCredit);
     }
 
-    public long getMessageCredit()
-    {
-        return _messageCredit.get();
-    }
-
-    public long getBytesCredit()
-    {
-        return -1L;
-    }
-
     public void restoreCredit(long messageCredit, long bytesCredit)
     {
         _messageCredit.addAndGet(messageCredit);
@@ -48,12 +41,6 @@
 
     }
 
-    public void removeAllCredit()
-    {
-        setSuspended(true);
-        _messageCredit.set(0L);
-    }
-
     public boolean hasCredit()
     {
         return _messageCredit.get() > 0L;
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/NoAckCreditManager.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/NoAckCreditManager.java
new file mode 100644
index 0000000..6e5aab2
--- /dev/null
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/NoAckCreditManager.java
@@ -0,0 +1,56 @@
+/*
+ * 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 org.apache.qpid.server.protocol.ServerProtocolEngine;
+import org.apache.qpid.server.flow.AbstractFlowCreditManager;
+
+public class NoAckCreditManager extends AbstractFlowCreditManager
+{
+    private final ServerProtocolEngine _serverProtocolEngine;
+
+    public NoAckCreditManager(ServerProtocolEngine serverProtocolEngine)
+    {
+        _serverProtocolEngine = serverProtocolEngine;
+    }
+
+    @Override
+    public void restoreCredit(final long messageCredit, final long bytesCredit)
+    {
+        setSuspended(!hasCredit());
+    }
+
+    @Override
+    public boolean hasCredit()
+    {
+        return !_serverProtocolEngine.isTransportBlockedForWriting();
+    }
+
+    @Override
+    public boolean useCreditForMessage(final long msgSize)
+    {
+        if (!hasCredit())
+        {
+            setSuspended(true);
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/flow/Pre0_10CreditManager.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/Pre0_10CreditManager.java
similarity index 85%
rename from qpid/java/broker-core/src/main/java/org/apache/qpid/server/flow/Pre0_10CreditManager.java
rename to qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/Pre0_10CreditManager.java
index fc2d4bf..a869a70 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/flow/Pre0_10CreditManager.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/Pre0_10CreditManager.java
@@ -18,20 +18,28 @@
 * under the License.
 *
 */
-package org.apache.qpid.server.flow;
+package org.apache.qpid.server.protocol.v0_8;
 
 
+import org.apache.qpid.server.protocol.ServerProtocolEngine;
+import org.apache.qpid.server.flow.AbstractFlowCreditManager;
+import org.apache.qpid.server.flow.FlowCreditManager;
+
 public class Pre0_10CreditManager extends AbstractFlowCreditManager implements FlowCreditManager
 {
 
+    private final ServerProtocolEngine _protocolEngine;
     private volatile long _bytesCreditLimit;
     private volatile long _messageCreditLimit;
 
     private volatile long _bytesCredit;
     private volatile long _messageCredit;
 
-    public Pre0_10CreditManager(long bytesCreditLimit, long messageCreditLimit)
+    public Pre0_10CreditManager(long bytesCreditLimit,
+                                long messageCreditLimit,
+                                ServerProtocolEngine protocolEngine)
     {
+        _protocolEngine = protocolEngine;
         _bytesCreditLimit = bytesCreditLimit;
         _messageCreditLimit = messageCreditLimit;
         _bytesCredit = bytesCreditLimit;
@@ -39,6 +47,7 @@
     }
 
 
+
     public synchronized void setCreditLimits(final long bytesCreditLimit, final long messageCreditLimit)
     {
         long bytesCreditChange = bytesCreditLimit - _bytesCreditLimit;
@@ -80,16 +89,6 @@
     }
 
 
-    public long getMessageCredit()
-    {
-        return _messageCredit;
-    }
-
-    public long getBytesCredit()
-    {
-        return _bytesCredit;
-    }
-
     public synchronized void restoreCredit(final long messageCredit, final long bytesCredit)
     {
         final long messageCreditLimit = _messageCreditLimit;
@@ -119,22 +118,21 @@
 
     }
 
-    public synchronized void removeAllCredit()
-    {
-        _bytesCredit = 0L;
-        _messageCredit = 0L;
-        setSuspended(!hasCredit());
-    }
-
     public synchronized boolean hasCredit()
     {
         return (_bytesCreditLimit == 0L || _bytesCredit > 0)
-                && (_messageCreditLimit == 0L || _messageCredit > 0);
+                && (_messageCreditLimit == 0L || _messageCredit > 0)
+                && !_protocolEngine.isTransportBlockedForWriting();
     }
 
     public synchronized boolean useCreditForMessage(final long msgSize)
     {
-        if(_messageCreditLimit != 0L)
+        if (_protocolEngine.isTransportBlockedForWriting())
+        {
+            setSuspended(true);
+            return false;
+        }
+        else if(_messageCreditLimit != 0L)
         {
             if(_messageCredit != 0L)
             {
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolEngineCreator_0_8.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolEngineCreator_0_8.java
index 0058fe8..e8cf028 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolEngineCreator_0_8.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolEngineCreator_0_8.java
@@ -20,7 +20,7 @@
  */
 package org.apache.qpid.server.protocol.v0_8;
 
-import org.apache.qpid.protocol.ServerProtocolEngine;
+import org.apache.qpid.server.protocol.ServerProtocolEngine;
 import org.apache.qpid.server.model.Broker;
 import org.apache.qpid.server.model.Protocol;
 import org.apache.qpid.server.model.Transport;
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolEngineCreator_0_9.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolEngineCreator_0_9.java
index 7253111..8817e79 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolEngineCreator_0_9.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolEngineCreator_0_9.java
@@ -20,7 +20,7 @@
  */
 package org.apache.qpid.server.protocol.v0_8;
 
-import org.apache.qpid.protocol.ServerProtocolEngine;
+import org.apache.qpid.server.protocol.ServerProtocolEngine;
 import org.apache.qpid.server.model.Broker;
 import org.apache.qpid.server.model.Protocol;
 import org.apache.qpid.server.model.Transport;
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolEngineCreator_0_9_1.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolEngineCreator_0_9_1.java
index e72cc4d..af37b17 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolEngineCreator_0_9_1.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolEngineCreator_0_9_1.java
@@ -20,7 +20,7 @@
  */
 package org.apache.qpid.server.protocol.v0_8;
 
-import org.apache.qpid.protocol.ServerProtocolEngine;
+import org.apache.qpid.server.protocol.ServerProtocolEngine;
 import org.apache.qpid.server.model.Broker;
 import org.apache.qpid.server.model.Protocol;
 import org.apache.qpid.server.model.Transport;
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolOutputConverterImpl.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolOutputConverterImpl.java
index b616aab..4a84cca 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolOutputConverterImpl.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolOutputConverterImpl.java
@@ -42,6 +42,7 @@
 import org.apache.qpid.server.message.ServerMessage;
 import org.apache.qpid.server.plugin.MessageConverter;
 import org.apache.qpid.server.protocol.MessageConverterRegistry;
+import org.apache.qpid.transport.ByteBufferSender;
 import org.apache.qpid.util.GZIPUtils;
 
 public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
@@ -255,6 +256,15 @@
             }
         }
 
+        @Override
+        public long writePayload(final ByteBufferSender sender) throws IOException
+        {
+            ByteBuffer buf = _message.getContent(_offset, _length);
+            long size = buf.remaining();
+            sender.send(buf.duplicate());
+            return size;
+        }
+
         public void handle(int channelId, AMQVersionAwareProtocolSession amqProtocolSession) throws AMQException
         {
             throw new UnsupportedOperationException();
@@ -346,6 +356,15 @@
             _underlyingBody.writePayload(buffer);
         }
 
+        public long writePayload(ByteBufferSender sender) throws IOException
+        {
+            if(_underlyingBody == null)
+            {
+                _underlyingBody = createAMQBody();
+            }
+            return _underlyingBody.writePayload(sender);
+        }
+
         public void handle(final int channelId, final AMQVersionAwareProtocolSession amqMinaProtocolSession)
             throws AMQException
         {
@@ -449,6 +468,18 @@
         }
 
         @Override
+        public long writePayload(final ByteBufferSender sender) throws IOException
+        {
+            long size = (new AMQFrame(_channel, _methodBody)).writePayload(sender);
+
+            size += (new AMQFrame(_channel, _headerBody)).writePayload(sender);
+
+            size += (new AMQFrame(_channel, _contentBody)).writePayload(sender);
+
+            return size;
+        }
+
+        @Override
         public String toString()
         {
             StringBuilder builder = new StringBuilder();
@@ -490,6 +521,14 @@
         }
 
         @Override
+        public long writePayload(final ByteBufferSender sender) throws IOException
+        {
+            long size = (new AMQFrame(_channel, _methodBody)).writePayload(sender);
+            size += (new AMQFrame(_channel, _headerBody)).writePayload(sender);
+            return size;
+        }
+
+        @Override
         public String toString()
         {
             StringBuilder builder = new StringBuilder();
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AckTest.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AckTest.java
index 9326f16..55fc865 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AckTest.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AckTest.java
@@ -31,8 +31,6 @@
 import org.apache.qpid.framing.ContentHeaderBody;
 import org.apache.qpid.framing.MessagePublishInfo;
 import org.apache.qpid.server.consumer.ConsumerImpl;
-import org.apache.qpid.server.flow.LimitlessCreditManager;
-import org.apache.qpid.server.flow.Pre0_10CreditManager;
 import org.apache.qpid.server.message.MessageInstance;
 import org.apache.qpid.server.queue.AMQQueue;
 import org.apache.qpid.server.store.StoredMessage;
@@ -328,7 +326,7 @@
     public void testMessageDequeueRestoresCreditTest() throws Exception
     {
         // Send 10 messages
-        Pre0_10CreditManager creditManager = new Pre0_10CreditManager(0l, 1);
+        Pre0_10CreditManager creditManager = new Pre0_10CreditManager(0l, 1, _protocolEngine);
 
 
         _subscriptionTarget = ConsumerTarget_0_8.createAckTarget(_channel, DEFAULT_CONSUMER_TAG, null, creditManager);
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/InternalTestProtocolSession.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/InternalTestProtocolSession.java
index 6c6b746..3a759cd 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/InternalTestProtocolSession.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/InternalTestProtocolSession.java
@@ -36,11 +36,11 @@
 import javax.security.auth.Subject;
 
 import org.apache.log4j.Logger;
+
 import org.apache.qpid.AMQException;
 import org.apache.qpid.framing.AMQShortString;
 import org.apache.qpid.framing.ContentHeaderBody;
 import org.apache.qpid.framing.MessagePublishInfo;
-import org.apache.qpid.protocol.AMQConstant;
 import org.apache.qpid.server.consumer.ConsumerImpl;
 import org.apache.qpid.server.message.InstanceProperties;
 import org.apache.qpid.server.message.MessageContentSource;
@@ -50,7 +50,7 @@
 import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
 import org.apache.qpid.server.security.auth.UsernamePrincipal;
 import org.apache.qpid.server.virtualhost.VirtualHostImpl;
-import org.apache.qpid.transport.Sender;
+import org.apache.qpid.transport.ByteBufferSender;
 import org.apache.qpid.transport.network.NetworkConnection;
 
 public class InternalTestProtocolSession extends AMQProtocolEngine implements ProtocolOutputConverter
@@ -224,17 +224,6 @@
         //  Then the AMQMinaProtocolSession can join on the returning future without a NPE.
     }
 
-    public void closeSession(AMQChannel session, AMQConstant cause, String message)
-    {
-        super.closeSession(session, cause, message);
-
-        //Simulate the Client responding with a CloseOK
-        // should really update the StateManger but we don't have access here
-        // changeState(AMQState.CONNECTION_CLOSED);
-        ((AMQChannel)session).getConnection().closeSession(false);
-
-    }
-
     private class InternalWriteDeliverMethod implements ClientDeliveryMethod
     {
         private int _channelId;
@@ -288,16 +277,12 @@
         private String _remoteHost = "127.0.0.1";
         private String _localHost = "127.0.0.1";
         private int _port = portNumber.incrementAndGet();
-        private final Sender<ByteBuffer> _sender;
+        private final ByteBufferSender _sender;
 
         public TestNetworkConnection()
         {
-            _sender = new Sender<ByteBuffer>()
+            _sender = new ByteBufferSender()
             {
-                public void setIdleTimeout(int i)
-                {
-                }
-
                 public void send(ByteBuffer msg)
                 {
                 }
@@ -358,7 +343,7 @@
         }
 
         @Override
-        public Sender<ByteBuffer> getSender()
+        public ByteBufferSender getSender()
         {
             return _sender;
         }
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/flow/LimitlessCreditManager.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/LimitlessCreditManager.java
similarity index 87%
rename from qpid/java/broker-core/src/main/java/org/apache/qpid/server/flow/LimitlessCreditManager.java
rename to qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/LimitlessCreditManager.java
index 89fc606..c4c89ac 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/flow/LimitlessCreditManager.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/LimitlessCreditManager.java
@@ -18,20 +18,14 @@
 * under the License.
 *
 */
-package org.apache.qpid.server.flow;
+package org.apache.qpid.server.protocol.v0_8;
 
 
+import org.apache.qpid.server.flow.AbstractFlowCreditManager;
+import org.apache.qpid.server.flow.FlowCreditManager;
+
 public class LimitlessCreditManager extends AbstractFlowCreditManager implements FlowCreditManager
 {
-    public long getMessageCredit()
-    {
-        return -1L;
-    }
-
-    public long getBytesCredit()
-    {
-        return -1L;
-    }
 
     public void restoreCredit(long messageCredit, long bytesCredit)
     {
diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java
index 8e24d55..b515fda 100644
--- a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java
+++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java
@@ -30,7 +30,9 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
+import java.util.Queue;
 import java.util.Set;
+import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.CopyOnWriteArrayList;
 
 import javax.security.auth.Subject;
@@ -51,6 +53,7 @@
 import org.apache.qpid.server.model.port.AmqpPort;
 import org.apache.qpid.server.protocol.AMQConnectionModel;
 import org.apache.qpid.server.protocol.AMQSessionModel;
+import org.apache.qpid.server.protocol.ServerProtocolEngine;
 import org.apache.qpid.server.protocol.SessionModelListener;
 import org.apache.qpid.server.security.SubjectCreator;
 import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
@@ -64,6 +67,7 @@
     private final AmqpPort<?> _port;
     private final Broker<?> _broker;
     private final SubjectCreator _subjectCreator;
+    private final ProtocolEngine_1_0_0_SASL _protocolEngine;
     private VirtualHostImpl _vhost;
     private final Transport _transport;
     private final ConnectionEndpoint _conn;
@@ -98,15 +102,24 @@
 
     private List<Action<? super Connection_1_0>> _closeTasks =
             Collections.synchronizedList(new ArrayList<Action<? super Connection_1_0>>());
+
+    private final Queue<Action<? super Connection_1_0>> _asyncTaskList =
+            new ConcurrentLinkedQueue<>();
+
+
     private boolean _closedOnOpen;
 
 
+
     public Connection_1_0(Broker<?> broker,
                           ConnectionEndpoint conn,
                           long connectionId,
                           AmqpPort<?> port,
-                          Transport transport, final SubjectCreator subjectCreator)
+                          Transport transport,
+                          final SubjectCreator subjectCreator,
+                          final ProtocolEngine_1_0_0_SASL protocolEngine)
     {
+        _protocolEngine = protocolEngine;
         _broker = broker;
         _port = port;
         _transport = transport;
@@ -207,6 +220,13 @@
         _closeTasks.add( task );
     }
 
+    private void addAsyncTask(final Action<Connection_1_0> action)
+    {
+        _asyncTaskList.add(action);
+        notifyWork();
+    }
+
+
     public void closeReceived()
     {
         Collection<Session_1_0> sessions = new ArrayList(_sessions);
@@ -245,9 +265,19 @@
 
 
     @Override
-    public void close(AMQConstant cause, String message)
+    public void closeAsync(AMQConstant cause, String message)
     {
-        _conn.close();
+        Action<Connection_1_0> action = new Action<Connection_1_0>()
+        {
+            @Override
+            public void performAction(final Connection_1_0 object)
+            {
+                _conn.close();
+
+            }
+        };
+        addAsyncTask(action);
+
     }
 
     @Override
@@ -263,9 +293,16 @@
     }
 
     @Override
-    public void closeSession(Session_1_0 session, AMQConstant cause, String message)
+    public void closeSessionAsync(final Session_1_0 session, final AMQConstant cause, final String message)
     {
-        session.close(cause, message);
+        addAsyncTask(new Action<Connection_1_0>()
+        {
+            @Override
+            public void performAction(final Connection_1_0 object)
+            {
+                session.close(cause, message);
+            }
+        });
     }
 
     @Override
@@ -363,6 +400,11 @@
         return _port;
     }
 
+    public ServerProtocolEngine getProtocolEngine()
+    {
+        return _protocolEngine;
+    }
+
     @Override
     public Transport getTransport()
     {
@@ -480,4 +522,38 @@
     }
 
 
+    public void transportStateChanged()
+    {
+        for (Session_1_0 session : _sessions)
+        {
+            session.transportStateChanged();
+        }
+    }
+
+    @Override
+    public void notifyWork()
+    {
+        _protocolEngine.notifyWork();
+    }
+
+    @Override
+    public boolean isMessageAssignmentSuspended()
+    {
+        return _protocolEngine.isMessageAssignmentSuspended();
+    }
+
+    public void processPending()
+    {
+        while(_asyncTaskList.peek() != null)
+        {
+            Action<? super Connection_1_0> asyncAction = _asyncTaskList.poll();
+            asyncAction.performAction(this);
+        }
+
+        for (AMQSessionModel session : getSessionModels())
+        {
+            session.processPending();
+        }
+
+    }
 }
diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ConsumerTarget_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ConsumerTarget_1_0.java
index 3b95218..fa2e543 100644
--- a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ConsumerTarget_1_0.java
+++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ConsumerTarget_1_0.java
@@ -40,6 +40,7 @@
 import org.apache.qpid.amqp_1_0.type.transaction.TransactionalState;
 import org.apache.qpid.amqp_1_0.type.transport.SenderSettleMode;
 import org.apache.qpid.amqp_1_0.type.transport.Transfer;
+import org.apache.qpid.server.protocol.ServerProtocolEngine;
 import org.apache.qpid.server.consumer.AbstractConsumerTarget;
 import org.apache.qpid.server.consumer.ConsumerImpl;
 import org.apache.qpid.server.message.MessageInstance;
@@ -83,9 +84,10 @@
         return _link.getEndpoint();
     }
 
-    public boolean isSuspended()
+    @Override
+    public boolean doIsSuspended()
     {
-        return _link.getSession().getConnectionModel().isStopped() || getState() != State.ACTIVE;// || !getEndpoint().hasCreditToSend();
+        return _link.getSession().getConnectionModel().isStopped() || getState() != State.ACTIVE;
 
     }
 
@@ -113,22 +115,10 @@
         }
     }
 
-    public long send(final ConsumerImpl consumer, MessageInstance entry, boolean batch)
+    public void doSend(final ConsumerImpl consumer, final MessageInstance entry, boolean batch)
     {
         // TODO
-        long size = entry.getMessage().getSize();
-        send(entry);
-        return size;
-    }
-
-    public void flushBatched()
-    {
-        // TODO
-    }
-
-    public void send(final MessageInstance queueEntry)
-    {
-        ServerMessage serverMessage = queueEntry.getMessage();
+        ServerMessage serverMessage = entry.getMessage();
         Message_1_0 message;
         if(serverMessage instanceof Message_1_0)
         {
@@ -168,7 +158,7 @@
             payload.flip();
         }
 
-        if(queueEntry.getDeliveryCount() != 0)
+        if(entry.getDeliveryCount() != 0)
         {
             payload = payload.duplicate();
             ValueHandler valueHandler = new ValueHandler(_typeRegistry);
@@ -200,7 +190,7 @@
                 header.setPriority(oldHeader.getPriority());
                 header.setTtl(oldHeader.getTtl());
             }
-            header.setDeliveryCount(UnsignedInteger.valueOf(queueEntry.getDeliveryCount()));
+            header.setDeliveryCount(UnsignedInteger.valueOf(entry.getDeliveryCount()));
             _sectionEncoder.reset();
             _sectionEncoder.encodeObject(header);
             Binary encodedHeader = _sectionEncoder.getEncoding();
@@ -230,10 +220,10 @@
                 else
                 {
                     UnsettledAction action = _acquires
-                                             ? new DispositionAction(tag, queueEntry)
-                                             : new DoNothingAction(tag, queueEntry);
+                                             ? new DispositionAction(tag, entry)
+                                             : new DoNothingAction(tag, entry);
 
-                    _link.addUnsettled(tag, action, queueEntry);
+                    _link.addUnsettled(tag, action, entry);
                 }
 
                 if(_transactionId != null)
@@ -257,9 +247,9 @@
 
                             public void onRollback()
                             {
-                                if(queueEntry.isAcquiredBy(getConsumer()))
+                                if(entry.isAcquiredBy(getConsumer()))
                                 {
-                                    queueEntry.release();
+                                    entry.release();
                                     _link.getEndpoint().updateDisposition(tag, (DeliveryState)null, true);
 
 
@@ -274,12 +264,17 @@
             }
             else
             {
-                queueEntry.release();
+                entry.release();
             }
         }
 
     }
 
+    public void flushBatched()
+    {
+        // TODO
+    }
+
     public void queueDeleted()
     {
         //TODO
@@ -296,7 +291,9 @@
     {
         synchronized (_link.getLock())
         {
-            final boolean hasCredit = _link.isAttached() && getEndpoint().hasCreditToSend();
+
+            ServerProtocolEngine protocolEngine = getSession().getConnection().getProtocolEngine();
+            final boolean hasCredit = _link.isAttached() && getEndpoint().hasCreditToSend() && !protocolEngine.isTransportBlockedForWriting();
             if(!hasCredit && getState() == State.ACTIVE)
             {
                 suspend();
@@ -336,7 +333,8 @@
     {
         synchronized(_link.getLock())
         {
-            if(isSuspended() && getEndpoint() != null)
+            ServerProtocolEngine protocolEngine = getSession().getConnection().getProtocolEngine();
+            if(isSuspended() && getEndpoint() != null && !protocolEngine.isTransportBlockedForWriting())
             {
                 updateState(State.SUSPENDED, State.ACTIVE);
                 _transactionId = _link.getTransactionId();
@@ -544,4 +542,9 @@
         return 0;
     }
 
+    @Override
+    protected void processClosed()
+    {
+
+    }
 }
diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngineCreator_1_0_0_SASL.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngineCreator_1_0_0_SASL.java
index fa8134c..e72dc17 100644
--- a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngineCreator_1_0_0_SASL.java
+++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngineCreator_1_0_0_SASL.java
@@ -20,7 +20,7 @@
  */
 package org.apache.qpid.server.protocol.v1_0;
 
-import org.apache.qpid.protocol.ServerProtocolEngine;
+import org.apache.qpid.server.protocol.ServerProtocolEngine;
 import org.apache.qpid.server.model.Broker;
 import org.apache.qpid.server.model.Protocol;
 import org.apache.qpid.server.model.Transport;
diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngine_1_0_0_SASL.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngine_1_0_0_SASL.java
index 740b01e..a0f10ee 100644
--- a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngine_1_0_0_SASL.java
+++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngine_1_0_0_SASL.java
@@ -29,6 +29,8 @@
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
 
 import javax.security.auth.Subject;
 import javax.security.sasl.SaslException;
@@ -52,14 +54,18 @@
 import org.apache.qpid.amqp_1_0.type.transport.Error;
 import org.apache.qpid.common.QpidProperties;
 import org.apache.qpid.common.ServerPropertyNames;
-import org.apache.qpid.protocol.ServerProtocolEngine;
+import org.apache.qpid.server.protocol.ServerProtocolEngine;
+import org.apache.qpid.server.consumer.ConsumerImpl;
 import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.Consumer;
 import org.apache.qpid.server.model.Transport;
 import org.apache.qpid.server.model.port.AmqpPort;
+import org.apache.qpid.server.protocol.AMQSessionModel;
 import org.apache.qpid.server.security.SubjectCreator;
 import org.apache.qpid.server.security.auth.UsernamePrincipal;
+import org.apache.qpid.server.util.Action;
 import org.apache.qpid.server.util.ServerScopedRuntimeException;
-import org.apache.qpid.transport.Sender;
+import org.apache.qpid.transport.ByteBufferSender;
 import org.apache.qpid.transport.TransportException;
 import org.apache.qpid.transport.network.NetworkConnection;
 
@@ -79,6 +85,9 @@
     private long _createTime = System.currentTimeMillis();
     private ConnectionEndpoint _endpoint;
     private long _connectionId;
+    private final AtomicBoolean _stateChanged = new AtomicBoolean();
+    private final AtomicReference<Action<ServerProtocolEngine>> _workListener = new AtomicReference<>();
+
 
     private static final ByteBuffer HEADER =
            ByteBuffer.wrap(new byte[]
@@ -116,8 +125,9 @@
     private byte _revision;
     private PrintWriter _out;
     private NetworkConnection _network;
-    private Sender<ByteBuffer> _sender;
+    private ByteBufferSender _sender;
     private Connection_1_0 _connection;
+    private volatile boolean _transportBlockedForWriting;
 
 
     static enum State {
@@ -134,6 +144,10 @@
 
     private State _state = State.A;
 
+    private final AtomicReference<Thread> _messageAssignmentSuspended = new AtomicReference<>();
+
+
+
 
     public ProtocolEngine_1_0_0_SASL(final NetworkConnection networkDriver, final Broker<?> broker,
                                      long id, AmqpPort<?> port, Transport transport)
@@ -149,6 +163,31 @@
     }
 
 
+    @Override
+    public boolean isMessageAssignmentSuspended()
+    {
+        Thread lock = _messageAssignmentSuspended.get();
+        return lock != null && _messageAssignmentSuspended.get() != Thread.currentThread();
+    }
+
+    @Override
+    public void setMessageAssignmentSuspended(final boolean messageAssignmentSuspended)
+    {
+        _messageAssignmentSuspended.set(messageAssignmentSuspended ? Thread.currentThread() : null);
+
+        if(!messageAssignmentSuspended)
+        {
+            for(AMQSessionModel<?,?> session : _connection.getSessionModels())
+            {
+                for(Consumer<?> consumer : session.getConsumers())
+                {
+                    ((ConsumerImpl)consumer).getTarget().notifyCurrentState();
+                }
+            }
+        }
+    }
+
+
     public SocketAddress getRemoteAddress()
     {
         return _network.getRemoteAddress();
@@ -179,7 +218,12 @@
         //Todo
     }
 
-    public void setNetworkConnection(final NetworkConnection network, final Sender<ByteBuffer> sender)
+    @Override
+    public void encryptedTransport()
+    {
+    }
+
+    public void setNetworkConnection(final NetworkConnection network, final ByteBufferSender sender)
     {
         _network = network;
         _sender = sender;
@@ -211,7 +255,7 @@
         _endpoint.setProperties(serverProperties);
 
         _endpoint.setRemoteAddress(getRemoteAddress());
-        _connection = new Connection_1_0(_broker, _endpoint, _connectionId, _port, _transport, subjectCreator);
+        _connection = new Connection_1_0(_broker, _endpoint, _connectionId, _port, _transport, subjectCreator, this);
 
         _endpoint.setConnectionEventListener(_connection);
         _endpoint.setFrameOutputHandler(this);
@@ -524,6 +568,8 @@
 
     }
 
+
+
     public void close()
     {
         _sender.close();
@@ -554,4 +600,60 @@
     {
         return _lastWriteTime;
     }
+
+    @Override
+    public boolean isTransportBlockedForWriting()
+    {
+        return _transportBlockedForWriting;
+    }
+    @Override
+    public void setTransportBlockedForWriting(final boolean blocked)
+    {
+        _transportBlockedForWriting = blocked;
+        _connection.transportStateChanged();
+
+    }
+
+    public void flushBatched()
+    {
+        _sender.flush();
+    }
+
+    @Override
+    public void processPending()
+    {
+        _connection.processPending();
+
+    }
+
+    @Override
+    public boolean hasWork()
+    {
+        return _stateChanged.get();
+    }
+
+    @Override
+    public void notifyWork()
+    {
+        _stateChanged.set(true);
+
+        final Action<ServerProtocolEngine> listener = _workListener.get();
+        if(listener != null)
+        {
+            listener.performAction(this);
+        }
+    }
+
+    @Override
+    public void clearWork()
+    {
+        _stateChanged.set(false);
+    }
+
+    @Override
+    public void setWorkListener(final Action<ServerProtocolEngine> listener)
+    {
+        _workListener.set(listener);
+    }
+
 }
diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java
index c952a3c..fe36ba9 100644
--- a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java
+++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java
@@ -729,4 +729,9 @@
     {
         return _consumer;
     }
+
+    public ConsumerTarget_1_0 getConsumerTarget()
+    {
+        return _target;
+    }
 }
diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java
index b9ee0ad..2a49e81 100644
--- a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java
+++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java
@@ -109,6 +109,7 @@
     private final Subject _subject = new Subject();
 
     private final CopyOnWriteArrayList<Consumer<?>> _consumers = new CopyOnWriteArrayList<Consumer<?>>();
+    private final CopyOnWriteArrayList<SendingLink_1_0> _sendingLinks = new CopyOnWriteArrayList<>();
     private final ConfigurationChangeListener _consumerClosedListener = new ConsumerClosedListener();
     private final CopyOnWriteArrayList<ConsumerListener> _consumerListeners = new CopyOnWriteArrayList<ConsumerListener>();
     private Session<?> _modelObject;
@@ -211,7 +212,7 @@
                         );
 
                         sendingLinkEndpoint.setLinkEventListener(new SubjectSpecificSendingLinkListener(sendingLink));
-                        registerConsumer(sendingLink.getConsumer());
+                        registerConsumer(sendingLink);
 
                         link = sendingLink;
                         if(TerminusDurability.UNSETTLED_STATE.equals(source.getDurable()) || TerminusDurability.CONFIGURATION.equals(source.getDurable()))
@@ -412,12 +413,14 @@
         }
     }
 
-    private void registerConsumer(final ConsumerImpl consumer)
+    private void registerConsumer(final SendingLink_1_0 link)
     {
+        ConsumerImpl consumer = link.getConsumer();
         if(consumer instanceof Consumer<?>)
         {
             Consumer<?> modelConsumer = (Consumer<?>) consumer;
             _consumers.add(modelConsumer);
+            _sendingLinks.add(link);
             modelConsumer.addChangeListener(_consumerClosedListener);
             consumerAdded(modelConsumer);
         }
@@ -615,6 +618,20 @@
     }
 
     @Override
+    public void transportStateChanged()
+    {
+        for(SendingLink_1_0 link : _sendingLinks)
+        {
+            ConsumerTarget_1_0 target = link.getConsumerTarget();
+            target.flowStateChanged();
+
+
+        }
+
+
+    }
+
+    @Override
     public LogSubject getLogSubject()
     {
         return this;
@@ -883,6 +900,16 @@
         return 0L;
     }
 
+    @Override
+    public void processPending()
+    {
+        for(Consumer<?> consumer : getConsumers())
+        {
+
+            ((ConsumerImpl)consumer).getTarget().processPending();
+        }
+    }
+
     private void consumerAdded(Consumer<?> consumer)
     {
         for(ConsumerListener l : _consumerListeners)
diff --git a/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/GenericAbstractJDBCMessageStore.java b/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/GenericAbstractJDBCMessageStore.java
index ce612ec..63c60d7 100644
--- a/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/GenericAbstractJDBCMessageStore.java
+++ b/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/GenericAbstractJDBCMessageStore.java
@@ -25,7 +25,7 @@
 
 import org.apache.qpid.server.model.ConfiguredObject;
 import org.apache.qpid.server.store.StoreException;
-import org.apache.qpid.server.store.StoreFuture;
+import org.apache.qpid.server.util.FutureResult;
 import org.apache.qpid.server.store.Transaction;
 
 public abstract class GenericAbstractJDBCMessageStore extends org.apache.qpid.server.store.AbstractJDBCMessageStore
@@ -131,7 +131,7 @@
         }
 
         @Override
-        public StoreFuture commitTranAsync()
+        public FutureResult commitTranAsync()
         {
             try
             {
diff --git a/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNodeConsumer.java b/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNodeConsumer.java
index 3f873a2..28d8a6c 100644
--- a/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNodeConsumer.java
+++ b/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNodeConsumer.java
@@ -24,6 +24,9 @@
 import java.util.Collections;
 import java.util.List;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
 import org.apache.qpid.server.consumer.ConsumerImpl;
 import org.apache.qpid.server.consumer.ConsumerTarget;
 import org.apache.qpid.server.message.MessageSource;
@@ -124,7 +127,6 @@
     @Override
     public void close()
     {
-
     }
 
     @Override
@@ -164,6 +166,12 @@
 
     }
 
+    @Override
+    public ConsumerTarget getTarget()
+    {
+        return _target;
+    }
+
     ManagementNode getManagementNode()
     {
         return _managementNode;
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
index 69920ff..1a85a24 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
+++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
@@ -39,6 +39,8 @@
 import javax.servlet.MultipartConfigElement;
 import javax.servlet.http.HttpServletRequest;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 import org.apache.log4j.Logger;
 import org.eclipse.jetty.server.Connector;
 import org.eclipse.jetty.server.Server;
@@ -130,7 +132,7 @@
     }
 
     @StateTransition(currentState = {State.UNINITIALIZED,State.ERRORED}, desiredState = State.ACTIVE)
-    private void doStart()
+    private ListenableFuture<Void> doStart()
     {
         getBroker().getEventLogger().message(ManagementConsoleMessages.STARTUP(OPERATIONAL_LOGGING_NAME));
 
@@ -148,6 +150,7 @@
 
         getBroker().getEventLogger().message(ManagementConsoleMessages.READY(OPERATIONAL_LOGGING_NAME));
         setState(State.ACTIVE);
+        return Futures.immediateFuture(null);
     }
 
     @Override
@@ -206,7 +209,9 @@
 
                 if(port.getState() != State.ACTIVE)
                 {
-                    port.start();
+
+                    // TODO - RG
+                    port.startAsync();
                 }
                 Connector connector = null;
 
diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/HttpManagementTest.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/HttpManagementTest.java
index 52d7ba3..4327292 100644
--- a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/HttpManagementTest.java
+++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/HttpManagementTest.java
@@ -30,6 +30,7 @@
 import java.util.UUID;
 
 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.AuthenticationProvider;
 import org.apache.qpid.server.model.Broker;
@@ -58,7 +59,9 @@
         when(_broker.getModel()).thenReturn(objectFactory.getModel());
         when(_broker.getCategoryClass()).thenReturn(Broker.class);
         when(_broker.getEventLogger()).thenReturn(mock(EventLogger.class));
-        when(_broker.getTaskExecutor()).thenReturn(mock(TaskExecutor.class));
+        TaskExecutor taskExecutor = new TaskExecutorImpl();
+        taskExecutor.start();
+        when(_broker.getTaskExecutor()).thenReturn(taskExecutor);
 
         Map<String, Object> attributes = new HashMap<String, Object>();
         attributes.put(HttpManagement.HTTP_BASIC_AUTHENTICATION_ENABLED, false);
diff --git a/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagementPluginImpl.java b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagementPluginImpl.java
index 6c962c2..06558b9 100644
--- a/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagementPluginImpl.java
+++ b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagementPluginImpl.java
@@ -32,6 +32,8 @@
 import javax.management.InstanceAlreadyExistsException;
 import javax.management.JMException;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 import org.apache.log4j.Logger;
 
 import org.apache.qpid.server.configuration.IllegalConfigurationException;
@@ -105,7 +107,7 @@
     }
 
     @StateTransition(currentState = {State.UNINITIALIZED,State.ERRORED}, desiredState = State.ACTIVE)
-    private void doStart() throws JMException, IOException
+    private ListenableFuture<Void> doStart() throws JMException, IOException
     {
         _allowPortActivation = true;
         Broker<?> broker = getBroker();
@@ -125,7 +127,8 @@
                 registryPort.setPortManager(this);
                 if(port.getState() != State.ACTIVE)
                 {
-                    port.start();
+                    // TODO - RG
+                    port.startAsync();
                 }
 
             }
@@ -135,7 +138,7 @@
                 connectorPort.setPortManager(this);
                 if(port.getState() != State.ACTIVE)
                 {
-                    port.start();
+                    port.startAsync();
                 }
 
             }
@@ -175,6 +178,7 @@
         _objectRegistry.start();
         setState(State.ACTIVE);
         _allowPortActivation = false;
+        return Futures.immediateFuture(null);
     }
 
     @Override
diff --git a/qpid/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketProvider.java b/qpid/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketProvider.java
index a194ac7..896a711 100644
--- a/qpid/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketProvider.java
+++ b/qpid/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketProvider.java
@@ -53,7 +53,7 @@
 import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory;
 import org.apache.qpid.server.transport.AcceptingTransport;
 import org.apache.qpid.server.util.ServerScopedRuntimeException;
-import org.apache.qpid.transport.Sender;
+import org.apache.qpid.transport.ByteBufferSender;
 import org.apache.qpid.transport.network.NetworkConnection;
 import org.apache.qpid.transport.network.security.ssl.SSLUtil;
 
@@ -81,9 +81,7 @@
         _supported = supported;
         _defaultSupportedProtocolReply = defaultSupportedProtocolReply;
         _factory = new MultiVersionProtocolEngineFactory(
-                        _port.getParent(Broker.class), null,
-                        _port.getWantClientAuth(),
-                        _port.getNeedClientAuth(),
+                        _port.getParent(Broker.class),
                         _supported,
                         _defaultSupportedProtocolReply,
                         _port,
@@ -242,7 +240,7 @@
         }
     }
 
-    private class ConnectionWrapper implements NetworkConnection, Sender<ByteBuffer>
+    private class ConnectionWrapper implements NetworkConnection, ByteBufferSender
     {
         private final WebSocket.Connection _connection;
         private final SocketAddress _localAddress;
@@ -261,7 +259,7 @@
         }
 
         @Override
-        public Sender<ByteBuffer> getSender()
+        public ByteBufferSender getSender()
         {
             return this;
         }
@@ -273,12 +271,6 @@
         }
 
         @Override
-        public void setIdleTimeout(final int i)
-        {
-
-        }
-
-        @Override
         public void send(final ByteBuffer msg)
         {
             try
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java
index ae83b6a..8176358 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java
@@ -34,7 +34,6 @@
 import javax.jms.JMSException;
 import javax.jms.XASession;
 
-import org.apache.qpid.transport.Receiver;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -60,6 +59,7 @@
 import org.apache.qpid.jms.ConnectionURL;
 import org.apache.qpid.jms.Session;
 import org.apache.qpid.properties.ConnectionStartProperties;
+import org.apache.qpid.transport.ByteBufferReceiver;
 import org.apache.qpid.transport.ConnectionSettings;
 import org.apache.qpid.transport.network.NetworkConnection;
 import org.apache.qpid.transport.network.OutgoingNetworkTransport;
@@ -522,12 +522,12 @@
     }
 
 
-    private static class ReceiverClosedWaiter implements Receiver<ByteBuffer>
+    private static class ReceiverClosedWaiter implements ByteBufferReceiver
     {
         private final CountDownLatch _closedWatcher;
-        private final Receiver<ByteBuffer> _receiver;
+        private final ByteBufferReceiver _receiver;
 
-        public ReceiverClosedWaiter(Receiver<ByteBuffer> receiver)
+        public ReceiverClosedWaiter(ByteBufferReceiver receiver)
         {
             _receiver = receiver;
             _closedWatcher = new CountDownLatch(1);
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionCloseMethodHandler.java b/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionCloseMethodHandler.java
index f038fc6..17b0fe1 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionCloseMethodHandler.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionCloseMethodHandler.java
@@ -20,8 +20,6 @@
  */
 package org.apache.qpid.client.handler;
 
-import java.nio.ByteBuffer;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -35,7 +33,7 @@
 import org.apache.qpid.framing.ConnectionCloseBody;
 import org.apache.qpid.framing.ConnectionCloseOkBody;
 import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.transport.Sender;
+import org.apache.qpid.transport.ByteBufferSender;
 import org.apache.qpid.transport.TransportException;
 
 public class ConnectionCloseMethodHandler implements StateAwareMethodListener<ConnectionCloseBody>
@@ -95,7 +93,7 @@
         }
         finally
         {
-            Sender<ByteBuffer> sender = session.getSender();
+            ByteBufferSender sender = session.getSender();
 
             if (error != null)
             {
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionRedirectMethodHandler.java b/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionRedirectMethodHandler.java
index ee7e2bf..6440f3e 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionRedirectMethodHandler.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionRedirectMethodHandler.java
@@ -30,7 +30,7 @@
 import org.apache.qpid.client.protocol.AMQProtocolSession;
 import org.apache.qpid.client.state.StateAwareMethodListener;
 import org.apache.qpid.framing.ConnectionRedirectBody;
-import org.apache.qpid.transport.Sender;
+import org.apache.qpid.transport.ByteBufferSender;
 import org.apache.qpid.transport.TransportException;
 
 public class ConnectionRedirectMethodHandler implements StateAwareMethodListener<ConnectionRedirectBody>
@@ -72,7 +72,7 @@
 
         session.notifyError(new ConnectionRedirectException(host,port));
 
-        Sender<ByteBuffer> sender = session.getSender();
+        ByteBufferSender sender = session.getSender();
 
         // Close the open TCP connection
         try
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java
index c1f5e4c..200b1d7 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java
@@ -66,8 +66,8 @@
 import org.apache.qpid.protocol.AMQMethodListener;
 import org.apache.qpid.protocol.ProtocolEngine;
 import org.apache.qpid.thread.Threading;
+import org.apache.qpid.transport.ByteBufferSender;
 import org.apache.qpid.transport.ConnectionSettings;
-import org.apache.qpid.transport.Sender;
 import org.apache.qpid.transport.TransportException;
 import org.apache.qpid.transport.network.NetworkConnection;
 import org.apache.qpid.util.BytesDataOutput;
@@ -179,7 +179,7 @@
 
 
     private NetworkConnection _network;
-    private Sender<ByteBuffer> _sender;
+    private ByteBufferSender _sender;
     private long _lastReadTime = System.currentTimeMillis();
     private long _lastWriteTime = System.currentTimeMillis();
     private HeartbeatListener _heartbeatListener = HeartbeatListener.DEFAULT;
@@ -316,6 +316,11 @@
         }
     }
 
+    @Override
+    public void encryptedTransport()
+    {
+    }
+
     public void readerIdle()
     {
         _logger.debug("Protocol Session [" + this + "] idle: reader");
@@ -892,7 +897,7 @@
         setNetworkConnection(network, network.getSender());
     }
 
-    public void setNetworkConnection(NetworkConnection network, Sender<ByteBuffer> sender)
+    public void setNetworkConnection(NetworkConnection network, ByteBufferSender sender)
     {
         _network = network;
         _sender = sender;
@@ -910,7 +915,7 @@
         return _lastWriteTime;
     }
 
-    protected Sender<ByteBuffer> getSender()
+    protected ByteBufferSender getSender()
     {
         return _sender;
     }
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java
index 0fd3e27..15cb908 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java
@@ -20,7 +20,6 @@
  */
 package org.apache.qpid.client.protocol;
 
-import java.nio.ByteBuffer;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
@@ -52,8 +51,8 @@
 import org.apache.qpid.framing.ProtocolVersion;
 import org.apache.qpid.protocol.AMQConstant;
 import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
+import org.apache.qpid.transport.ByteBufferSender;
 import org.apache.qpid.transport.ConnectionSettings;
-import org.apache.qpid.transport.Sender;
 import org.apache.qpid.transport.TransportException;
 
 /**
@@ -382,7 +381,7 @@
         }
     }
 
-    public Sender<ByteBuffer> getSender()
+    public ByteBufferSender getSender()
     {
         return _protocolHandler.getSender();
     }
@@ -471,7 +470,7 @@
         _protocolHandler.propagateExceptionToAllWaiters(error);
     }
 
-    public void setSender(Sender<java.nio.ByteBuffer> sender)
+    public void setSender(ByteBufferSender sender)
     {
         // No-op, interface munging
     }
diff --git a/qpid/java/client/src/test/java/org/apache/qpid/client/AMQSession_0_10Test.java b/qpid/java/client/src/test/java/org/apache/qpid/client/AMQSession_0_10Test.java
index 8a7e6ab..2543c5b 100644
--- a/qpid/java/client/src/test/java/org/apache/qpid/client/AMQSession_0_10Test.java
+++ b/qpid/java/client/src/test/java/org/apache/qpid/client/AMQSession_0_10Test.java
@@ -666,11 +666,11 @@
         }
     }
 
-    class MockSender implements Sender<ProtocolEvent>
+    class MockSender implements ProtocolEventSender
     {
         private List<ProtocolEvent> _sendEvents = new ArrayList<ProtocolEvent>();
 
-        public void setIdleTimeout(int i)
+        private void setIdleTimeout(int i)
         {
         }
 
diff --git a/qpid/java/client/src/test/java/org/apache/qpid/client/transport/MockSender.java b/qpid/java/client/src/test/java/org/apache/qpid/client/transport/MockSender.java
index 7c3988c1..ee6704b 100644
--- a/qpid/java/client/src/test/java/org/apache/qpid/client/transport/MockSender.java
+++ b/qpid/java/client/src/test/java/org/apache/qpid/client/transport/MockSender.java
@@ -22,16 +22,11 @@
 
 import java.nio.ByteBuffer;
 
-import org.apache.qpid.transport.Sender;
+import org.apache.qpid.transport.ByteBufferSender;
 
-public class MockSender implements Sender<ByteBuffer>
+public class MockSender implements ByteBufferSender
 {
 
-    public void setIdleTimeout(int i)
-    {
-
-    }
-
     public void send(ByteBuffer msg)
     {
 
diff --git a/qpid/java/client/src/test/java/org/apache/qpid/client/transport/TestNetworkConnection.java b/qpid/java/client/src/test/java/org/apache/qpid/client/transport/TestNetworkConnection.java
index c9af1de..cdfa835 100644
--- a/qpid/java/client/src/test/java/org/apache/qpid/client/transport/TestNetworkConnection.java
+++ b/qpid/java/client/src/test/java/org/apache/qpid/client/transport/TestNetworkConnection.java
@@ -20,18 +20,18 @@
  */
 package org.apache.qpid.client.transport;
 
-import java.security.Principal;
-import org.apache.qpid.protocol.ProtocolEngineFactory;
-import org.apache.qpid.ssl.SSLContextFactory;
-import org.apache.qpid.transport.NetworkTransportConfiguration;
-import org.apache.qpid.transport.Sender;
-import org.apache.qpid.transport.network.NetworkConnection;
-
 import java.net.BindException;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
 import java.nio.ByteBuffer;
+import java.security.Principal;
+
+import org.apache.qpid.protocol.ProtocolEngineFactory;
+import org.apache.qpid.ssl.SSLContextFactory;
+import org.apache.qpid.transport.ByteBufferSender;
+import org.apache.qpid.transport.NetworkTransportConfiguration;
+import org.apache.qpid.transport.network.NetworkConnection;
 
 /**
  * Test implementation of IoSession, which is required for some tests. Methods not being used are not implemented,
@@ -147,7 +147,7 @@
         _remoteAddress = address;
     }
 
-    public Sender<ByteBuffer> getSender()
+    public ByteBufferSender getSender()
     {
         return _sender;
     }
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQBody.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQBody.java
index cb0c78e..6860b46 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQBody.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQBody.java
@@ -20,12 +20,13 @@
  */
 package org.apache.qpid.framing;
 
-import org.apache.qpid.AMQException;
-import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
-
 import java.io.DataOutput;
 import java.io.IOException;
 
+import org.apache.qpid.AMQException;
+import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
+import org.apache.qpid.transport.ByteBufferSender;
+
 public interface AMQBody
 {
     public  byte getFrameType();
@@ -39,4 +40,6 @@
     public void writePayload(DataOutput buffer) throws IOException;
     
     void handle(final int channelId, final AMQVersionAwareProtocolSession amqProtocolSession) throws AMQException;
+
+    long writePayload(ByteBufferSender sender) throws IOException;
 }
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlock.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlock.java
index c234a5e..8f804bf 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlock.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlock.java
@@ -23,6 +23,8 @@
 import java.io.DataOutput;
 import java.io.IOException;
 
+import org.apache.qpid.transport.ByteBufferSender;
+
 
 /**
  * A data block represents something that has a size in bytes and the ability to write itself to a byte
@@ -44,4 +46,6 @@
      */
     public abstract void writePayload(DataOutput buffer) throws IOException;
 
+    public abstract long writePayload(ByteBufferSender sender) throws IOException;
+
 }
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQFrame.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQFrame.java
index 83397c3..5fcdfb9 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQFrame.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQFrame.java
@@ -22,6 +22,10 @@
 
 import java.io.DataOutput;
 import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import org.apache.qpid.transport.ByteBufferSender;
+import org.apache.qpid.util.BytesDataOutput;
 
 public class AMQFrame extends AMQDataBlock implements EncodableAMQDataBlock
 {
@@ -57,6 +61,25 @@
         buffer.writeByte(FRAME_END_BYTE);
     }
 
+    private static final byte[] FRAME_END_BYTE_ARRAY = new byte[] { FRAME_END_BYTE };
+
+    @Override
+    public long writePayload(final ByteBufferSender sender) throws IOException
+    {
+        byte[] frameHeader = new byte[7];
+        BytesDataOutput buffer = new BytesDataOutput(frameHeader);
+
+        buffer.writeByte(_bodyFrame.getFrameType());
+        EncodingUtils.writeUnsignedShort(buffer, _channel);
+        EncodingUtils.writeUnsignedInteger(buffer, _bodyFrame.getSize());
+        sender.send(ByteBuffer.wrap(frameHeader));
+
+        long size = 8 + _bodyFrame.writePayload(sender);
+
+        sender.send(ByteBuffer.wrap(FRAME_END_BYTE_ARRAY));
+        return size;
+    }
+
     public final int getChannel()
     {
         return _channel;
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyImpl.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyImpl.java
index e40452e..01deed6 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyImpl.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBodyImpl.java
@@ -24,12 +24,15 @@
 import java.io.DataInput;
 import java.io.DataOutput;
 import java.io.IOException;
+import java.nio.ByteBuffer;
 
 import org.apache.qpid.AMQChannelException;
 import org.apache.qpid.AMQConnectionException;
 import org.apache.qpid.AMQException;
 import org.apache.qpid.protocol.AMQConstant;
 import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
+import org.apache.qpid.transport.ByteBufferSender;
+import org.apache.qpid.util.BytesDataOutput;
 
 public abstract class AMQMethodBodyImpl implements AMQMethodBody
 {
@@ -105,6 +108,16 @@
         writeMethodPayload(buffer);
     }
 
+    @Override
+    public long writePayload(final ByteBufferSender sender) throws IOException
+    {
+        final int size = getSize();
+        byte[] bytes = new byte[size];
+        BytesDataOutput buffer = new BytesDataOutput(bytes);
+        writePayload(buffer);
+        sender.send(ByteBuffer.wrap(bytes));
+        return size;
+    }
 
     protected int getSizeOf(AMQShortString string)
     {
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java
index ef0da9b..6481c6e 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java
@@ -23,10 +23,14 @@
 import java.io.DataInput;
 import java.io.DataOutput;
 import java.io.IOException;
+import java.nio.ByteBuffer;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import org.apache.qpid.transport.ByteBufferSender;
+import org.apache.qpid.util.BytesDataOutput;
+
 public class BasicContentHeaderProperties
 {
     //persistent & non-persistent constants, values as per JMS DeliveryMode
@@ -314,6 +318,26 @@
         }
     }
 
+
+    public long writePropertyListPayload(final ByteBufferSender sender) throws IOException
+    {
+        if(useEncodedForm())
+        {
+            sender.send(ByteBuffer.wrap(_encodedForm));
+            return _encodedForm.length;
+        }
+        else
+        {
+            int propertyListSize = getPropertyListSize();
+            byte[] data = new byte[propertyListSize];
+            BytesDataOutput out = new BytesDataOutput(data);
+            writePropertyListPayload(out);
+            sender.send(ByteBuffer.wrap(data));
+            return propertyListSize;
+        }
+
+    }
+
     public void populatePropertiesFromBuffer(DataInput buffer, int propertyFlags, int size) throws AMQFrameDecodingException, IOException
     {
         _propertyFlags = propertyFlags;
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/CompositeAMQDataBlock.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/CompositeAMQDataBlock.java
index 098e365..8194460 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/CompositeAMQDataBlock.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/CompositeAMQDataBlock.java
@@ -23,6 +23,8 @@
 import java.io.DataOutput;
 import java.io.IOException;
 
+import org.apache.qpid.transport.ByteBufferSender;
+
 public class CompositeAMQDataBlock extends AMQDataBlock implements EncodableAMQDataBlock
 {
 
@@ -58,6 +60,17 @@
         }
     }
 
+    @Override
+    public long writePayload(final ByteBufferSender sender) throws IOException
+    {
+        long size = 0l;
+        for (int i = 0; i < _blocks.length; i++)
+        {
+            size += _blocks[i].writePayload(sender);
+        }
+        return size;
+    }
+
     public String toString()
     {
         if (_blocks == null)
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/ContentBody.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/ContentBody.java
index 5c322f3..0f4ba52 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/ContentBody.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/ContentBody.java
@@ -28,6 +28,7 @@
 import org.apache.qpid.AMQException;
 import org.apache.qpid.codec.MarkableDataInput;
 import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
+import org.apache.qpid.transport.ByteBufferSender;
 
 public class ContentBody implements AMQBody
 {
@@ -72,6 +73,20 @@
         session.contentBodyReceived(channelId, this);
     }
 
+    @Override
+    public long writePayload(final ByteBufferSender sender) throws IOException
+    {
+        if(_payload != null)
+        {
+            sender.send(ByteBuffer.wrap(_payload));
+            return _payload.length;
+        }
+        else
+        {
+            return 0l;
+        }
+    }
+
     public byte[] getPayload()
     {
         return _payload;
@@ -133,6 +148,23 @@
             }
         }
 
+        @Override
+        public long writePayload(final ByteBufferSender sender) throws IOException
+        {
+            if(_buf.hasArray())
+            {
+                sender.send(ByteBuffer.wrap(_buf.array(), _buf.arrayOffset() + _offset, _length));
+            }
+            else
+            {
+                ByteBuffer buf = _buf.duplicate();
+
+                buf.position(_offset);
+                buf.limit(_offset+_length);
+                sender.send(buf);
+            }
+            return _length;
+        }
 
         public void handle(int channelId, AMQVersionAwareProtocolSession amqProtocolSession) throws AMQException
         {
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBody.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBody.java
index 377d2e1..21b8e6c 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBody.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBody.java
@@ -24,10 +24,13 @@
 import java.io.DataInputStream;
 import java.io.DataOutput;
 import java.io.IOException;
+import java.nio.ByteBuffer;
 
 import org.apache.qpid.AMQException;
 import org.apache.qpid.codec.MarkableDataInput;
 import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
+import org.apache.qpid.transport.ByteBufferSender;
+import org.apache.qpid.util.BytesDataOutput;
 
 public class ContentHeaderBody implements AMQBody
 {
@@ -98,6 +101,19 @@
         _properties.writePropertyListPayload(buffer);
     }
 
+    @Override
+    public long writePayload(final ByteBufferSender sender) throws IOException
+    {
+        byte[] data = new byte[14];
+        BytesDataOutput buffer = new BytesDataOutput(data);
+        EncodingUtils.writeUnsignedShort(buffer, CLASS_ID);
+        EncodingUtils.writeUnsignedShort(buffer, 0);
+        buffer.writeLong(_bodySize);
+        EncodingUtils.writeUnsignedShort(buffer, _properties.getPropertyFlags());
+        sender.send(ByteBuffer.wrap(data));
+        return 14 + _properties.writePropertyListPayload(sender);
+    }
+
     public void handle(final int channelId, final AMQVersionAwareProtocolSession session)
             throws AMQException
     {
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBody.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBody.java
index b5f854e..3afc082 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBody.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBody.java
@@ -27,6 +27,7 @@
 import org.apache.qpid.AMQException;
 import org.apache.qpid.codec.MarkableDataInput;
 import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
+import org.apache.qpid.transport.ByteBufferSender;
 
 public class HeartbeatBody implements AMQBody
 {
@@ -61,6 +62,12 @@
     {
     }
 
+    @Override
+    public long writePayload(final ByteBufferSender sender) throws IOException
+    {
+        return 0l;
+    }
+
     public void handle(final int channelId, final AMQVersionAwareProtocolSession session)
             throws AMQException
     {
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/ProtocolInitiation.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/ProtocolInitiation.java
index ed1935c..9c8d2a8 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/framing/ProtocolInitiation.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/ProtocolInitiation.java
@@ -23,11 +23,14 @@
 import java.io.DataOutput;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 
 import org.apache.qpid.AMQException;
 import org.apache.qpid.codec.MarkableDataInput;
+import org.apache.qpid.transport.ByteBufferSender;
+import org.apache.qpid.util.BytesDataOutput;
 
 public class ProtocolInitiation extends AMQDataBlock implements EncodableAMQDataBlock
 {
@@ -88,6 +91,16 @@
         buffer.write(_protocolMinor);
     }
 
+    @Override
+    public long writePayload(final ByteBufferSender sender) throws IOException
+    {
+        byte[] data = new byte[8];
+        BytesDataOutput out = new BytesDataOutput(data);
+        writePayload(out);
+        sender.send(ByteBuffer.wrap(data));
+        return 8l;
+    }
+
     public boolean equals(Object o)
     {
         if (!(o instanceof ProtocolInitiation))
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/protocol/AMQVersionAwareProtocolSession.java b/qpid/java/common/src/main/java/org/apache/qpid/protocol/AMQVersionAwareProtocolSession.java
index 0c643f6..73c8653 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/protocol/AMQVersionAwareProtocolSession.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/protocol/AMQVersionAwareProtocolSession.java
@@ -26,9 +26,7 @@
 import org.apache.qpid.framing.ContentHeaderBody;
 import org.apache.qpid.framing.HeartbeatBody;
 import org.apache.qpid.framing.MethodRegistry;
-import org.apache.qpid.transport.Sender;
-
-import java.nio.ByteBuffer;
+import org.apache.qpid.transport.ByteBufferSender;
 
 
 /**
@@ -56,6 +54,6 @@
     public void heartbeatBodyReceived(int channelId, HeartbeatBody body) throws AMQException;
 
 
-    public void setSender(Sender<ByteBuffer> sender);
+    public void setSender(ByteBufferSender sender);
 
 }
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngine.java b/qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngine.java
index 6774d0a..f73f6d9 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngine.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/protocol/ProtocolEngine.java
@@ -20,19 +20,18 @@
  */
 package org.apache.qpid.protocol;
 
-import org.apache.qpid.transport.Receiver;
-import org.apache.qpid.transport.Sender;
+import java.net.SocketAddress;
+
+import org.apache.qpid.transport.ByteBufferReceiver;
+import org.apache.qpid.transport.ByteBufferSender;
 import org.apache.qpid.transport.network.NetworkConnection;
 import org.apache.qpid.transport.network.TransportActivity;
 
-import java.net.SocketAddress;
-import java.nio.ByteBuffer;
-
 /**
  * A ProtocolEngine is a Receiver for java.nio.ByteBuffers. It takes the data passed to it in the received
  * decodes it and then process the result.
  */
-public interface ProtocolEngine extends Receiver<java.nio.ByteBuffer>, TransportActivity
+public interface ProtocolEngine extends ByteBufferReceiver, TransportActivity
 {
    // Returns the remote address of the NetworkDriver
    SocketAddress getRemoteAddress();
@@ -56,7 +55,8 @@
    // Called when the NetworkEngine has not read data for the specified period of time (will close the connection)
    void readerIdle();
 
+   void encryptedTransport();
 
-   public void setNetworkConnection(NetworkConnection network, Sender<ByteBuffer> sender);
+   public void setNetworkConnection(NetworkConnection network, ByteBufferSender sender);
 
-}
\ No newline at end of file
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/Binding.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/Binding.java
index 8418c42..f703c01 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/Binding.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/Binding.java
@@ -26,11 +26,11 @@
  *
  */
 
-public interface Binding<E,T>
+public interface Binding<E>
 {
 
-    E endpoint(Sender<T> sender);
+    E endpoint(ByteBufferSender sender);
 
-    Receiver<T> receiver(E endpoint);
+    ByteBufferReceiver receiver(E endpoint);
 
 }
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/Receiver.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/ByteBufferReceiver.java
similarity index 90%
copy from qpid/java/common/src/main/java/org/apache/qpid/transport/Receiver.java
copy to qpid/java/common/src/main/java/org/apache/qpid/transport/ByteBufferReceiver.java
index 2a99458..1015f06 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/Receiver.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/ByteBufferReceiver.java
@@ -20,19 +20,13 @@
  */
 package org.apache.qpid.transport;
 
+import java.nio.ByteBuffer;
 
-/**
- * Receiver
- *
- */
-
-public interface Receiver<T>
+public interface ByteBufferReceiver
 {
-
-    void received(T msg);
+    void received(ByteBuffer msg);
 
     void exception(Throwable t);
 
     void closed();
-
 }
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/Sender.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/ByteBufferSender.java
similarity index 89%
rename from qpid/java/common/src/main/java/org/apache/qpid/transport/Sender.java
rename to qpid/java/common/src/main/java/org/apache/qpid/transport/ByteBufferSender.java
index 6519702..7dcaf61 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/Sender.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/ByteBufferSender.java
@@ -20,20 +20,13 @@
  */
 package org.apache.qpid.transport;
 
+import java.nio.ByteBuffer;
 
-/**
- * Sender
- *
- */
-
-public interface Sender<T>
+public interface ByteBufferSender
 {
-    void setIdleTimeout(int i);
-
-    void send(T msg);
+    void send(ByteBuffer msg);
 
     void flush();
 
     void close();
-
 }
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/ClientDelegate.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/ClientDelegate.java
index f8eabef..7c4e264 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/ClientDelegate.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/ClientDelegate.java
@@ -153,11 +153,9 @@
                               maxFrameSize,
                               actualHeartbeatInterval);
 
-        int idleTimeout = (int)(actualHeartbeatInterval * 1000 * heartbeatTimeoutFactor);
         conn.getNetworkConnection().setMaxReadIdle((int)(actualHeartbeatInterval*heartbeatTimeoutFactor));
         conn.getNetworkConnection().setMaxWriteIdle(actualHeartbeatInterval);
         conn.setMaxFrameSize(maxFrameSize == 0 ? 0xffff : maxFrameSize);
-        conn.setIdleTimeout(idleTimeout);
 
         int channelMax = tune.getChannelMax();
         //0 means no implied limit, except available server resources
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/Connection.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/Connection.java
index 331f96d..4ae7e8d 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/Connection.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/Connection.java
@@ -27,7 +27,6 @@
 import static org.apache.qpid.transport.Connection.State.OPENING;
 
 import java.net.SocketAddress;
-import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -68,7 +67,7 @@
  */
 
 public class Connection extends ConnectionInvoker
-    implements Receiver<ProtocolEvent>, Sender<ProtocolEvent>
+    implements ProtocolEventReceiver, ProtocolEventSender
 {
 
     protected static final Logger log = Logger.get(Connection.class);
@@ -120,7 +119,7 @@
     private SessionFactory _sessionFactory = DEFAULT_SESSION_FACTORY;
 
     private ConnectionDelegate delegate;
-    private Sender<ProtocolEvent> sender;
+    private ProtocolEventSender sender;
 
     final private Map<Binary,Session> sessions = new HashMap<Binary,Session>();
     final private Map<Integer,Session> channels = new ConcurrentHashMap<Integer,Session>();
@@ -163,15 +162,14 @@
         return Collections.unmodifiableList(listeners);
     }
 
-    public Sender<ProtocolEvent> getSender()
+    public ProtocolEventSender getSender()
     {
         return sender;
     }
 
-    public void setSender(Sender<ProtocolEvent> sender)
+    public void setSender(ProtocolEventSender sender)
     {
         this.sender = sender;
-        sender.setIdleTimeout(idleTimeout);
     }
 
     protected void setState(State state)
@@ -248,7 +246,7 @@
             OutgoingNetworkTransport transport = Transport.getOutgoingTransportInstance(ProtocolVersion.v0_10);
             final InputHandler inputHandler = new InputHandler(new Assembler(this));
             addFrameSizeObserver(inputHandler);
-            Receiver<ByteBuffer> secureReceiver = securityLayer.receiver(inputHandler);
+            ByteBufferReceiver secureReceiver = securityLayer.receiver(inputHandler);
             if(secureReceiver instanceof ConnectionListener)
             {
                 addConnectionListener((ConnectionListener)secureReceiver);
@@ -260,7 +258,7 @@
             setRemoteAddress(_networkConnection.getRemoteAddress());
             setLocalAddress(_networkConnection.getLocalAddress());
 
-            final Sender<ByteBuffer> secureSender = securityLayer.sender(_networkConnection.getSender());
+            final ByteBufferSender secureSender = securityLayer.sender(_networkConnection.getSender());
             if(secureSender instanceof ConnectionListener)
             {
                 addConnectionListener((ConnectionListener)secureSender);
@@ -425,7 +423,7 @@
         {
             log.debug("SEND: [%s] %s", this, event);
         }
-        Sender<ProtocolEvent> s = sender;
+        ProtocolEventSender s = sender;
         if (s == null)
         {
             throw new ConnectionException("connection closed");
@@ -439,7 +437,7 @@
         {
             log.debug("FLUSH: [%s]", this);
         }
-        final Sender<ProtocolEvent> theSender = sender;
+        final ProtocolEventSender theSender = sender;
         if(theSender != null)
         {
             theSender.flush();
@@ -631,6 +629,12 @@
         close(ConnectionCloseCode.CONNECTION_FORCED, "The connection was closed using the broker's management interface.");
     }
 
+
+    protected void sendConnectionClose(ConnectionCloseCode replyCode, String replyText, Option ... _options)
+    {
+        connectionClose(replyCode, replyText, _options);
+    }
+
     public void close(ConnectionCloseCode replyCode, String replyText, Option ... _options)
     {
         synchronized (lock)
@@ -690,20 +694,6 @@
         }
     }
 
-    public void setIdleTimeout(int i)
-    {
-        idleTimeout = i;
-        if (sender != null)
-        {
-            sender.setIdleTimeout(i);
-        }
-    }
-
-    public int getIdleTimeout()
-    {
-        return idleTimeout;
-    }
-
     public String getUserID()
     {
         return userID;
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/Receiver.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkEventReceiver.java
similarity index 87%
copy from qpid/java/common/src/main/java/org/apache/qpid/transport/Receiver.java
copy to qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkEventReceiver.java
index 2a99458..8b9c3f4 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/Receiver.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/NetworkEventReceiver.java
@@ -20,19 +20,13 @@
  */
 package org.apache.qpid.transport;
 
+import org.apache.qpid.transport.network.NetworkEvent;
 
-/**
- * Receiver
- *
- */
-
-public interface Receiver<T>
+public interface NetworkEventReceiver
 {
-
-    void received(T msg);
+    void received(NetworkEvent msg);
 
     void exception(Throwable t);
 
     void closed();
-
 }
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/Receiver.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/ProtocolEventReceiver.java
similarity index 91%
rename from qpid/java/common/src/main/java/org/apache/qpid/transport/Receiver.java
rename to qpid/java/common/src/main/java/org/apache/qpid/transport/ProtocolEventReceiver.java
index 2a99458..e4ab540 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/Receiver.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/ProtocolEventReceiver.java
@@ -20,19 +20,11 @@
  */
 package org.apache.qpid.transport;
 
-
-/**
- * Receiver
- *
- */
-
-public interface Receiver<T>
+public interface ProtocolEventReceiver
 {
-
-    void received(T msg);
+    void received(ProtocolEvent msg);
 
     void exception(Throwable t);
 
     void closed();
-
 }
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/Sender.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/ProtocolEventSender.java
similarity index 89%
copy from qpid/java/common/src/main/java/org/apache/qpid/transport/Sender.java
copy to qpid/java/common/src/main/java/org/apache/qpid/transport/ProtocolEventSender.java
index 6519702..418f31b 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/Sender.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/ProtocolEventSender.java
@@ -20,20 +20,11 @@
  */
 package org.apache.qpid.transport;
 
-
-/**
- * Sender
- *
- */
-
-public interface Sender<T>
+public interface ProtocolEventSender
 {
-    void setIdleTimeout(int i);
-
-    void send(T msg);
+    void send(ProtocolEvent msg);
 
     void flush();
 
     void close();
-
 }
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java
index 82a677b..f8fd286 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java
@@ -126,8 +126,11 @@
 
     protected void connectionAuthFailed(final Connection conn, Exception e)
     {
-        conn.exception(e);
-        conn.connectionClose(ConnectionCloseCode.CONNECTION_FORCED, e.getMessage());
+        if (e != null)
+        {
+            conn.exception(e);
+        }
+        conn.connectionClose(ConnectionCloseCode.CONNECTION_FORCED, e == null ? "Authentication failed" : e.getMessage());
     }
 
     protected void connectionAuthContinue(final Connection conn, byte[] challenge)
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java
index 2b93697..070621d 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java
@@ -20,12 +20,6 @@
  */
 package org.apache.qpid.transport.codec;
 
-import org.apache.qpid.transport.Range;
-import org.apache.qpid.transport.RangeSet;
-import org.apache.qpid.transport.Struct;
-import org.apache.qpid.transport.Type;
-
-import org.apache.qpid.transport.Xid;
 import static org.apache.qpid.transport.util.Functions.lsb;
 
 import java.io.UnsupportedEncodingException;
@@ -36,6 +30,12 @@
 import java.util.Map;
 import java.util.UUID;
 
+import org.apache.qpid.transport.Range;
+import org.apache.qpid.transport.RangeSet;
+import org.apache.qpid.transport.Struct;
+import org.apache.qpid.transport.Type;
+import org.apache.qpid.transport.Xid;
+
 
 /**
  * AbstractEncoder
@@ -43,7 +43,7 @@
  * @author Rafael H. Schloming
  */
 
-abstract class AbstractEncoder implements Encoder
+public abstract class AbstractEncoder implements Encoder
 {
 
     private static Map<Class<?>,Type> ENCODINGS = new HashMap<Class<?>,Type>();
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/codec/BBEncoder.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/codec/BBEncoder.java
index d9150be..407df71 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/codec/BBEncoder.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/codec/BBEncoder.java
@@ -360,8 +360,4 @@
 		}
 	}
 
-	public void writeMagicNumber()
-	{
-		out.put("AM2".getBytes());
-	}	
-}
\ No newline at end of file
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/codec/Encoder.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/codec/Encoder.java
index a9eea13..b5ab29c 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/codec/Encoder.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/codec/Encoder.java
@@ -20,13 +20,14 @@
  */
 package org.apache.qpid.transport.codec;
 
-import org.apache.qpid.transport.RangeSet;
-import org.apache.qpid.transport.Struct;
-
+import java.nio.ByteBuffer;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 
+import org.apache.qpid.transport.RangeSet;
+import org.apache.qpid.transport.Struct;
+
 
 /**
  * Encoder interface.
@@ -274,9 +275,10 @@
      * @param bytes the bytes array to be encoded.
      */
     void writeBin128(byte [] bytes);
-    
-    /**
-     * Encodes the AMQP magic number.
-     */
-    void writeMagicNumber();
-}
\ No newline at end of file
+
+    int position();
+
+    ByteBuffer underlyingBuffer();
+
+    void init();
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java
index a80b988..a7e9616 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java
@@ -20,28 +20,29 @@
  */
 package org.apache.qpid.transport.network;
 
-import org.apache.qpid.transport.DeliveryProperties;
-import org.apache.qpid.transport.Header;
-import org.apache.qpid.transport.MessageProperties;
-import org.apache.qpid.transport.Method;
-import org.apache.qpid.transport.ProtocolError;
-import org.apache.qpid.transport.ProtocolEvent;
-import org.apache.qpid.transport.ProtocolHeader;
-import org.apache.qpid.transport.Receiver;
-import org.apache.qpid.transport.Struct;
-import org.apache.qpid.transport.codec.BBDecoder;
-
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.qpid.transport.DeliveryProperties;
+import org.apache.qpid.transport.Header;
+import org.apache.qpid.transport.MessageProperties;
+import org.apache.qpid.transport.Method;
+import org.apache.qpid.transport.NetworkEventReceiver;
+import org.apache.qpid.transport.ProtocolError;
+import org.apache.qpid.transport.ProtocolEvent;
+import org.apache.qpid.transport.ProtocolEventReceiver;
+import org.apache.qpid.transport.ProtocolHeader;
+import org.apache.qpid.transport.Struct;
+import org.apache.qpid.transport.codec.BBDecoder;
+
 /**
  * Assembler
  *
  */
-public class Assembler implements Receiver<NetworkEvent>, NetworkDelegate
+public class Assembler implements NetworkEventReceiver, NetworkDelegate
 {
     // Use a small array to store incomplete Methods for low-value channels, instead of allocating a huge
     // array or always boxing the channelId and looking it up in the map. This value must be of the form 2^X - 1.
@@ -49,7 +50,7 @@
     private final Method[] _incompleteMethodArray = new Method[ARRAY_SIZE + 1];
     private final Map<Integer, Method> _incompleteMethodMap = new HashMap<Integer, Method>();
 
-    private final Receiver<ProtocolEvent> receiver;
+    private final ProtocolEventReceiver receiver;
     private final Map<Integer,List<Frame>> segments;
     private static final ThreadLocal<BBDecoder> _decoder = new ThreadLocal<BBDecoder>()
     {
@@ -59,7 +60,7 @@
         }
     };
 
-    public Assembler(Receiver<ProtocolEvent> receiver)
+    public Assembler(ProtocolEventReceiver receiver)
     {
         this.receiver = receiver;
         segments = new HashMap<Integer,List<Frame>>();
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/ConnectionBinding.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/ConnectionBinding.java
index 26e8f18..5463cd2 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/ConnectionBinding.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/ConnectionBinding.java
@@ -20,15 +20,13 @@
  */
 package org.apache.qpid.transport.network;
 
-import java.nio.ByteBuffer;
-
 import org.apache.qpid.transport.Binding;
+import org.apache.qpid.transport.ByteBufferReceiver;
+import org.apache.qpid.transport.ByteBufferSender;
 import org.apache.qpid.transport.Connection;
 import org.apache.qpid.transport.ConnectionDelegate;
 import org.apache.qpid.transport.ConnectionListener;
 import org.apache.qpid.transport.Constant;
-import org.apache.qpid.transport.Receiver;
-import org.apache.qpid.transport.Sender;
 import org.apache.qpid.transport.network.security.sasl.SASLReceiver;
 import org.apache.qpid.transport.network.security.sasl.SASLSender;
 
@@ -38,10 +36,10 @@
  */
 
 public abstract class ConnectionBinding
-    implements Binding<Connection,ByteBuffer>
+    implements Binding<Connection>
 {
 
-    public static Binding<Connection,ByteBuffer> get(final Connection connection)
+    public static Binding<Connection> get(final Connection connection)
     {
         return new ConnectionBinding()
         {
@@ -52,7 +50,7 @@
         };
     }
 
-    public static Binding<Connection,ByteBuffer> get(final ConnectionDelegate delegate)
+    public static Binding<Connection> get(final ConnectionDelegate delegate)
     {
         return new ConnectionBinding()
         {
@@ -69,7 +67,7 @@
 
     public abstract Connection connection();
 
-    public Connection endpoint(Sender<ByteBuffer> sender)
+    public Connection endpoint(ByteBufferSender sender)
     {
         Connection conn = connection();
 
@@ -87,7 +85,7 @@
         return conn;
     }
 
-    public Receiver<ByteBuffer> receiver(Connection conn)
+    public ByteBufferReceiver receiver(Connection conn)
     {
         final InputHandler inputHandler = new InputHandler(new Assembler(conn));
         conn.addFrameSizeObserver(inputHandler);
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/Disassembler.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/Disassembler.java
index a804cb2..c45b204 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/Disassembler.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/Disassembler.java
@@ -30,27 +30,29 @@
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 
+import org.apache.qpid.transport.ByteBufferSender;
 import org.apache.qpid.transport.FrameSizeObserver;
 import org.apache.qpid.transport.Header;
 import org.apache.qpid.transport.Method;
 import org.apache.qpid.transport.ProtocolDelegate;
 import org.apache.qpid.transport.ProtocolError;
 import org.apache.qpid.transport.ProtocolEvent;
+import org.apache.qpid.transport.ProtocolEventSender;
 import org.apache.qpid.transport.ProtocolHeader;
 import org.apache.qpid.transport.SegmentType;
-import org.apache.qpid.transport.Sender;
 import org.apache.qpid.transport.Struct;
 import org.apache.qpid.transport.codec.BBEncoder;
+import org.apache.qpid.transport.codec.Encoder;
 
 /**
  * Disassembler
  */
-public final class Disassembler implements Sender<ProtocolEvent>, ProtocolDelegate<Void>, FrameSizeObserver
+public final class Disassembler implements ProtocolEventSender, ProtocolDelegate<Void>, FrameSizeObserver
 {
-    private final Sender<ByteBuffer> sender;
+    private final ByteBufferSender sender;
     private int maxPayload;
     private final Object sendlock = new Object();
-    private final static ThreadLocal<BBEncoder> _encoder = new ThreadLocal<BBEncoder>()
+    private final static ThreadLocal<Encoder> _encoder = new ThreadLocal<Encoder>()
     {
         public BBEncoder initialValue()
         {
@@ -58,7 +60,7 @@
         }
     };
 
-    public Disassembler(Sender<ByteBuffer> sender, int maxFrame)
+    public Disassembler(ByteBufferSender sender, int maxFrame)
     {
         this.sender = sender;
         if (maxFrame <= HEADER_SIZE || maxFrame >= 64*1024)
@@ -174,7 +176,7 @@
 
     private void method(Method method, SegmentType type)
     {
-        BBEncoder enc = _encoder.get();
+        Encoder enc = _encoder.get();
         enc.init();
         enc.writeUint16(method.getEncodedType());
         if (type == SegmentType.COMMAND)
@@ -251,11 +253,6 @@
         throw new IllegalArgumentException(String.valueOf(error));
     }
 
-    public void setIdleTimeout(int i)
-    {
-        sender.setIdleTimeout(i);
-    }
-
     @Override
     public void setMaxFrameSize(final int maxFrame)
     {
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/IncomingNetworkTransport.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/IncomingNetworkTransport.java
index e0cd9ca..f378c54 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/IncomingNetworkTransport.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/IncomingNetworkTransport.java
@@ -20,6 +20,8 @@
  */
 package org.apache.qpid.transport.network;
 
+import java.util.Set;
+
 import javax.net.ssl.SSLContext;
 
 import org.apache.qpid.protocol.ProtocolEngineFactory;
@@ -29,7 +31,8 @@
 {
     public void accept(NetworkTransportConfiguration config,
                        ProtocolEngineFactory factory,
-                       SSLContext sslContext);
+                       SSLContext sslContext,
+                       final Set<TransportEncryption> encryptionSet);
 
     public int getAcceptingPort();
 }
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/InputHandler.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/InputHandler.java
index 758c2e1..a58bed5 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/InputHandler.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/InputHandler.java
@@ -29,11 +29,12 @@
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 
+import org.apache.qpid.transport.ByteBufferReceiver;
 import org.apache.qpid.transport.Constant;
 import org.apache.qpid.transport.FrameSizeObserver;
+import org.apache.qpid.transport.NetworkEventReceiver;
 import org.apache.qpid.transport.ProtocolError;
 import org.apache.qpid.transport.ProtocolHeader;
-import org.apache.qpid.transport.Receiver;
 import org.apache.qpid.transport.SegmentType;
 
 
@@ -43,7 +44,7 @@
  * @author Rafael H. Schloming
  */
 
-public class InputHandler implements Receiver<ByteBuffer>, FrameSizeObserver
+public class InputHandler implements ByteBufferReceiver, FrameSizeObserver
 {
 
     private int _maxFrameSize = Constant.MIN_MAX_FRAME_SIZE;
@@ -56,7 +57,7 @@
         ERROR
     }
 
-    private final Receiver<NetworkEvent> receiver;
+    private final NetworkEventReceiver receiver;
     private State state;
     private ByteBuffer input = null;
     private int needed;
@@ -66,7 +67,7 @@
     private byte track;
     private int channel;
 
-    public InputHandler(Receiver<NetworkEvent> receiver, State state)
+    public InputHandler(NetworkEventReceiver receiver, State state)
     {
         this.receiver = receiver;
         this.state = state;
@@ -82,7 +83,7 @@
         }
     }
 
-    public InputHandler(Receiver<NetworkEvent> receiver)
+    public InputHandler(NetworkEventReceiver receiver)
     {
         this(receiver, PROTO_HDR);
     }
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/NetworkConnection.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/NetworkConnection.java
index 2810e7a..bef266f 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/NetworkConnection.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/NetworkConnection.java
@@ -21,13 +21,13 @@
 package org.apache.qpid.transport.network;
 
 import java.net.SocketAddress;
-import java.nio.ByteBuffer;
 import java.security.Principal;
-import org.apache.qpid.transport.Sender;
+
+import org.apache.qpid.transport.ByteBufferSender;
 
 public interface NetworkConnection
 {
-    Sender<ByteBuffer> getSender();
+    ByteBufferSender getSender();
 
     void start();
 
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/OutgoingNetworkTransport.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/OutgoingNetworkTransport.java
index 45231aa..f2735f1 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/OutgoingNetworkTransport.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/OutgoingNetworkTransport.java
@@ -20,16 +20,14 @@
  */
 package org.apache.qpid.transport.network;
 
+import org.apache.qpid.transport.ByteBufferReceiver;
 import org.apache.qpid.transport.ConnectionSettings;
-import org.apache.qpid.transport.Receiver;
-
-import java.nio.ByteBuffer;
 
 public interface OutgoingNetworkTransport extends NetworkTransport
 {
     public NetworkConnection getConnection();
 
     public NetworkConnection connect(ConnectionSettings settings,
-                                     Receiver<ByteBuffer> delegate,
+                                     ByteBufferReceiver delegate,
                                      TransportActivity transportActivity);
-}
\ No newline at end of file
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/Receiver.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/TransportEncryption.java
similarity index 82%
copy from qpid/java/common/src/main/java/org/apache/qpid/transport/Receiver.java
copy to qpid/java/common/src/main/java/org/apache/qpid/transport/network/TransportEncryption.java
index 2a99458..b3f1f1c 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/Receiver.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/TransportEncryption.java
@@ -18,21 +18,9 @@
  * under the License.
  *
  */
-package org.apache.qpid.transport;
+package org.apache.qpid.transport.network;
 
-
-/**
- * Receiver
- *
- */
-
-public interface Receiver<T>
+public enum TransportEncryption
 {
-
-    void received(T msg);
-
-    void exception(Throwable t);
-
-    void closed();
-
+    NONE, TLS
 }
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/AbstractNetworkTransport.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/AbstractNetworkTransport.java
new file mode 100644
index 0000000..8d19c5a
--- /dev/null
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/AbstractNetworkTransport.java
@@ -0,0 +1,342 @@
+/*
+ *
+ * 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.transport.network.io;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.util.Set;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLServerSocketFactory;
+
+import org.slf4j.LoggerFactory;
+
+import org.apache.qpid.configuration.CommonProperties;
+import org.apache.qpid.protocol.ProtocolEngine;
+import org.apache.qpid.protocol.ProtocolEngineFactory;
+import org.apache.qpid.transport.ByteBufferReceiver;
+import org.apache.qpid.transport.ConnectionSettings;
+import org.apache.qpid.transport.NetworkTransportConfiguration;
+import org.apache.qpid.transport.TransportException;
+import org.apache.qpid.transport.network.IncomingNetworkTransport;
+import org.apache.qpid.transport.network.NetworkConnection;
+import org.apache.qpid.transport.network.OutgoingNetworkTransport;
+import org.apache.qpid.transport.network.TransportActivity;
+import org.apache.qpid.transport.network.TransportEncryption;
+import org.apache.qpid.transport.network.security.ssl.SSLUtil;
+
+// TODO we are no longer using the IncomingNetworkTransport
+public abstract class AbstractNetworkTransport implements OutgoingNetworkTransport, IncomingNetworkTransport
+{
+    private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(AbstractNetworkTransport.class);
+    private static final int TIMEOUT = Integer.getInteger(CommonProperties.IO_NETWORK_TRANSPORT_TIMEOUT_PROP_NAME,
+                                                              CommonProperties.IO_NETWORK_TRANSPORT_TIMEOUT_DEFAULT);
+    private static final int HANSHAKE_TIMEOUT = Integer.getInteger(CommonProperties.HANDSHAKE_TIMEOUT_PROP_NAME ,
+                                                                  CommonProperties.HANDSHAKE_TIMEOUT_DEFAULT);
+    private Socket _socket;
+    private NetworkConnection _connection;
+    private AcceptingThread _acceptor;
+
+    public NetworkConnection connect(ConnectionSettings settings,
+                                     ByteBufferReceiver delegate,
+                                     TransportActivity transportActivity)
+    {
+        int sendBufferSize = settings.getWriteBufferSize();
+        int receiveBufferSize = settings.getReadBufferSize();
+
+        try
+        {
+            _socket = new Socket();
+            _socket.setReuseAddress(true);
+            _socket.setTcpNoDelay(settings.isTcpNodelay());
+            _socket.setSendBufferSize(sendBufferSize);
+            _socket.setReceiveBufferSize(receiveBufferSize);
+
+            if(LOGGER.isDebugEnabled())
+            {
+                LOGGER.debug("SO_RCVBUF : " + _socket.getReceiveBufferSize());
+                LOGGER.debug("SO_SNDBUF : " + _socket.getSendBufferSize());
+                LOGGER.debug("TCP_NODELAY : " + _socket.getTcpNoDelay());
+            }
+
+            InetAddress address = InetAddress.getByName(settings.getHost());
+
+            _socket.connect(new InetSocketAddress(address, settings.getPort()), settings.getConnectTimeout());
+        }
+        catch (SocketException e)
+        {
+            throw new TransportException("Error connecting to broker", e);
+        }
+        catch (IOException e)
+        {
+            throw new TransportException("Error connecting to broker", e);
+        }
+
+        try
+        {
+            IdleTimeoutTicker ticker = new IdleTimeoutTicker(transportActivity, TIMEOUT);
+            _connection = createNetworkConnection(_socket, delegate, sendBufferSize, receiveBufferSize, TIMEOUT, ticker);
+            ticker.setConnection(_connection);
+            _connection.start();
+        }
+        catch(Exception e)
+        {
+            try
+            {
+                _socket.close();
+            }
+            catch(IOException ioe)
+            {
+                //ignored, throw based on original exception
+            }
+
+            throw new TransportException("Error creating network connection", e);
+        }
+
+        return _connection;
+    }
+
+    public void close()
+    {
+        if(_connection != null)
+        {
+            _connection.close();
+        }
+        if(_acceptor != null)
+        {
+            _acceptor.close();
+        }
+    }
+
+    public NetworkConnection getConnection()
+    {
+        return _connection;
+    }
+
+    public void accept(NetworkTransportConfiguration config,
+                       ProtocolEngineFactory factory,
+                       SSLContext sslContext, final Set<TransportEncryption> encryptionSet)
+    {
+        try
+        {
+            _acceptor = new AcceptingThread(config, factory, sslContext);
+            _acceptor.setDaemon(false);
+            _acceptor.start();
+        }
+        catch (IOException e)
+        {
+            throw new TransportException("Failed to start AMQP on port : " + config, e);
+        }
+    }
+
+    public int getAcceptingPort()
+    {
+        return _acceptor == null ? -1 : _acceptor.getPort();
+    }
+
+    protected abstract NetworkConnection createNetworkConnection(Socket socket,
+                                                                 ByteBufferReceiver engine,
+                                                                 Integer sendBufferSize,
+                                                                 Integer receiveBufferSize,
+                                                                 int timeout,
+                                                                 IdleTimeoutTicker ticker);
+
+    private class AcceptingThread extends Thread
+    {
+        private volatile boolean _closed = false;
+        private NetworkTransportConfiguration _config;
+        private ProtocolEngineFactory _factory;
+        private SSLContext _sslContext;
+        private ServerSocket _serverSocket;
+        private int _timeout;
+
+        private AcceptingThread(NetworkTransportConfiguration config,
+                                ProtocolEngineFactory factory,
+                                SSLContext sslContext) throws IOException
+        {
+            _config = config;
+            _factory = factory;
+            _sslContext = sslContext;
+            _timeout = TIMEOUT;
+
+            InetSocketAddress address = config.getAddress();
+
+            if(sslContext == null)
+            {
+                _serverSocket = new ServerSocket();
+            }
+            else
+            {
+                SSLServerSocketFactory socketFactory = _sslContext.getServerSocketFactory();
+                _serverSocket = socketFactory.createServerSocket();
+
+                SSLServerSocket sslServerSocket = (SSLServerSocket) _serverSocket;
+
+                SSLUtil.removeSSLv3Support(sslServerSocket);
+
+                if(config.needClientAuth())
+                {
+                    sslServerSocket.setNeedClientAuth(true);
+                }
+                else if(config.wantClientAuth())
+                {
+                    sslServerSocket.setWantClientAuth(true);
+                }
+
+            }
+
+            _serverSocket.setReuseAddress(true);
+            _serverSocket.bind(address);
+        }
+
+
+        /**
+            Close the underlying ServerSocket if it has not already been closed.
+         */
+        public void close()
+        {
+            LOGGER.debug("Shutting down the Acceptor");
+            _closed = true;
+
+            if (!_serverSocket.isClosed())
+            {
+                try
+                {
+                    _serverSocket.close();
+                }
+                catch (IOException e)
+                {
+                    throw new TransportException(e);
+                }
+            }
+        }
+
+        private int getPort()
+        {
+            return _serverSocket.getLocalPort();
+        }
+
+        @Override
+        public void run()
+        {
+            try
+            {
+                while (!_closed)
+                {
+                    Socket socket = null;
+                    try
+                    {
+                        socket = _serverSocket.accept();
+
+                        ProtocolEngine engine = _factory.newProtocolEngine(socket.getRemoteSocketAddress());
+
+                        if(engine != null)
+                        {
+                            socket.setTcpNoDelay(_config.getTcpNoDelay());
+                            socket.setSoTimeout(1000 * HANSHAKE_TIMEOUT);
+
+                            final Integer sendBufferSize = _config.getSendBufferSize();
+                            final Integer receiveBufferSize = _config.getReceiveBufferSize();
+
+                            socket.setSendBufferSize(sendBufferSize);
+                            socket.setReceiveBufferSize(receiveBufferSize);
+
+
+                            final IdleTimeoutTicker ticker = new IdleTimeoutTicker(engine, TIMEOUT);
+
+                            NetworkConnection connection =
+                                    createNetworkConnection(socket,
+                                                            engine,
+                                                            sendBufferSize,
+                                                            receiveBufferSize,
+                                                            _timeout,
+                                                            ticker);
+
+                            connection.setMaxReadIdle(HANSHAKE_TIMEOUT);
+
+                            ticker.setConnection(connection);
+
+                            engine.setNetworkConnection(connection, connection.getSender());
+
+                            connection.start();
+                        }
+                        else
+                        {
+                            socket.close();
+                        }
+                    }
+                    catch(RuntimeException e)
+                    {
+                        LOGGER.error("Error in Acceptor thread on address " + _config.getAddress(), e);
+                        closeSocketIfNecessary(socket);
+                    }
+                    catch(IOException e)
+                    {
+                        if(!_closed)
+                        {
+                            LOGGER.error("Error in Acceptor thread on address " + _config.getAddress(), e);
+                            closeSocketIfNecessary(socket);
+                            try
+                            {
+                                //Delay to avoid tight spinning the loop during issues such as too many open files
+                                Thread.sleep(1000);
+                            }
+                            catch (InterruptedException ie)
+                            {
+                                LOGGER.debug("Stopping acceptor due to interrupt request");
+                                _closed = true;
+                            }
+                        }
+                    }
+                }
+            }
+            finally
+            {
+                if(LOGGER.isDebugEnabled())
+                {
+                    LOGGER.debug("Acceptor exiting, no new connections will be accepted on address "
+                                 + _config.getAddress());
+                }
+            }
+        }
+
+        private void closeSocketIfNecessary(final Socket socket)
+        {
+            if(socket != null)
+            {
+                try
+                {
+                    socket.close();
+                }
+                catch (IOException e)
+                {
+                    LOGGER.debug("Exception while closing socket", e);
+                }
+            }
+        }
+
+    }
+}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IdleTimeoutTicker.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IdleTimeoutTicker.java
index 54a2a36..71704fc 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IdleTimeoutTicker.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IdleTimeoutTicker.java
@@ -25,7 +25,7 @@
 import org.apache.qpid.transport.network.Ticker;
 import org.apache.qpid.transport.network.TransportActivity;
 
-class IdleTimeoutTicker implements Ticker
+public class IdleTimeoutTicker implements Ticker
 {
     private final TransportActivity _transport;
     private final int _defaultTimeout;
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkConnection.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkConnection.java
index 5c3124c..5008849 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkConnection.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkConnection.java
@@ -22,7 +22,6 @@
 
 import java.net.Socket;
 import java.net.SocketAddress;
-import java.nio.ByteBuffer;
 import java.security.Principal;
 
 import javax.net.ssl.SSLPeerUnverifiedException;
@@ -31,8 +30,8 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import org.apache.qpid.transport.Receiver;
-import org.apache.qpid.transport.Sender;
+import org.apache.qpid.transport.ByteBufferReceiver;
+import org.apache.qpid.transport.ByteBufferSender;
 import org.apache.qpid.transport.network.NetworkConnection;
 import org.apache.qpid.transport.network.Ticker;
 
@@ -49,7 +48,7 @@
     private boolean _principalChecked;
     private final Object _lock = new Object();
 
-    public IoNetworkConnection(Socket socket, Receiver<ByteBuffer> delegate,
+    public IoNetworkConnection(Socket socket, ByteBufferReceiver delegate,
             int sendBufferSize, int receiveBufferSize, long timeout, Ticker ticker)
     {
         _socket = socket;
@@ -70,7 +69,7 @@
         _ioReceiver.initiate();
     }
 
-    public Sender<ByteBuffer> getSender()
+    public ByteBufferSender getSender()
     {
         return _ioSender;
     }
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java
index b7998ab..ccab1d9 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java
@@ -20,313 +20,24 @@
  */
 package org.apache.qpid.transport.network.io;
 
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.ServerSocket;
 import java.net.Socket;
-import java.net.SocketException;
-import java.nio.ByteBuffer;
 
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLServerSocket;
-import javax.net.ssl.SSLServerSocketFactory;
+import org.apache.qpid.transport.ByteBufferReceiver;
 
-import org.slf4j.LoggerFactory;
-
-import org.apache.qpid.configuration.CommonProperties;
-import org.apache.qpid.protocol.ProtocolEngine;
-import org.apache.qpid.protocol.ProtocolEngineFactory;
-import org.apache.qpid.transport.ConnectionSettings;
-import org.apache.qpid.transport.NetworkTransportConfiguration;
-import org.apache.qpid.transport.Receiver;
-import org.apache.qpid.transport.TransportException;
-import org.apache.qpid.transport.network.IncomingNetworkTransport;
-import org.apache.qpid.transport.network.NetworkConnection;
-import org.apache.qpid.transport.network.OutgoingNetworkTransport;
-import org.apache.qpid.transport.network.TransportActivity;
-import org.apache.qpid.transport.network.security.ssl.SSLUtil;
-
-public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNetworkTransport
+public class IoNetworkTransport extends AbstractNetworkTransport
 {
-    private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(IoNetworkTransport.class);
-    private static final int TIMEOUT = Integer.getInteger(CommonProperties.IO_NETWORK_TRANSPORT_TIMEOUT_PROP_NAME,
-                                                              CommonProperties.IO_NETWORK_TRANSPORT_TIMEOUT_DEFAULT);
-    private static final int HANSHAKE_TIMEOUT = Integer.getInteger(CommonProperties.HANDSHAKE_TIMEOUT_PROP_NAME ,
-                                                                  CommonProperties.HANDSHAKE_TIMEOUT_DEFAULT);
 
 
-    private Socket _socket;
-    private IoNetworkConnection _connection;
-    private AcceptingThread _acceptor;
-
-    public NetworkConnection connect(ConnectionSettings settings,
-                                     Receiver<ByteBuffer> delegate,
-                                     TransportActivity transportActivity)
+    @Override
+    protected IoNetworkConnection createNetworkConnection(final Socket socket,
+                                                       final ByteBufferReceiver engine,
+                                                       final Integer sendBufferSize,
+                                                       final Integer receiveBufferSize,
+                                                       final int timeout,
+                                                       final IdleTimeoutTicker ticker)
     {
-        int sendBufferSize = settings.getWriteBufferSize();
-        int receiveBufferSize = settings.getReadBufferSize();
-
-        try
-        {
-            _socket = new Socket();
-            _socket.setReuseAddress(true);
-            _socket.setTcpNoDelay(settings.isTcpNodelay());
-            _socket.setSendBufferSize(sendBufferSize);
-            _socket.setReceiveBufferSize(receiveBufferSize);
-
-            if(LOGGER.isDebugEnabled())
-            {
-                LOGGER.debug("SO_RCVBUF : " + _socket.getReceiveBufferSize());
-                LOGGER.debug("SO_SNDBUF : " + _socket.getSendBufferSize());
-                LOGGER.debug("TCP_NODELAY : " + _socket.getTcpNoDelay());
-            }
-
-            InetAddress address = InetAddress.getByName(settings.getHost());
-
-            _socket.connect(new InetSocketAddress(address, settings.getPort()), settings.getConnectTimeout());
-        }
-        catch (SocketException e)
-        {
-            throw new TransportException("Error connecting to broker", e);
-        }
-        catch (IOException e)
-        {
-            throw new TransportException("Error connecting to broker", e);
-        }
-
-        try
-        {
-            IdleTimeoutTicker ticker = new IdleTimeoutTicker(transportActivity, TIMEOUT);
-            _connection = new IoNetworkConnection(_socket, delegate, sendBufferSize, receiveBufferSize, TIMEOUT, ticker);
-            ticker.setConnection(_connection);
-            _connection.start();
-        }
-        catch(Exception e)
-        {
-            try
-            {
-                _socket.close();
-            }
-            catch(IOException ioe)
-            {
-                //ignored, throw based on original exception
-            }
-
-            throw new TransportException("Error creating network connection", e);
-        }
-
-        return _connection;
-    }
-
-    public void close()
-    {
-        if(_connection != null)
-        {
-            _connection.close();
-        }
-        if(_acceptor != null)
-        {
-            _acceptor.close();
-        }
-    }
-
-    public NetworkConnection getConnection()
-    {
-        return _connection;
-    }
-
-    public void accept(NetworkTransportConfiguration config,
-                       ProtocolEngineFactory factory,
-                       SSLContext sslContext)
-    {
-        try
-        {
-            _acceptor = new AcceptingThread(config, factory, sslContext);
-            _acceptor.setName(String.format("IoNetworkAcceptor - %s", config.getAddress()));
-            _acceptor.setDaemon(false);
-            _acceptor.start();
-        }
-        catch (IOException e)
-        {
-            throw new TransportException("Failed to start AMQP on port : " + config, e);
-        }
-    }
-
-    public int getAcceptingPort()
-    {
-        return _acceptor == null ? -1 : _acceptor.getPort();
-    }
-
-    private class AcceptingThread extends Thread
-    {
-        private volatile boolean _closed = false;
-        private NetworkTransportConfiguration _config;
-        private ProtocolEngineFactory _factory;
-        private SSLContext _sslContext;
-        private ServerSocket _serverSocket;
-        private int _timeout;
-
-        private AcceptingThread(NetworkTransportConfiguration config,
-                                ProtocolEngineFactory factory,
-                                SSLContext sslContext) throws IOException
-        {
-            _config = config;
-            _factory = factory;
-            _sslContext = sslContext;
-            _timeout = TIMEOUT;
-
-            InetSocketAddress address = config.getAddress();
-
-            if(sslContext == null)
-            {
-                _serverSocket = new ServerSocket();
-            }
-            else
-            {
-                SSLServerSocketFactory socketFactory = _sslContext.getServerSocketFactory();
-                _serverSocket = socketFactory.createServerSocket();
-
-                SSLServerSocket sslServerSocket = (SSLServerSocket) _serverSocket;
-
-                SSLUtil.removeSSLv3Support(sslServerSocket);
-                SSLUtil.updateEnabledCipherSuites(sslServerSocket, config.getEnabledCipherSuites(), config.getDisabledCipherSuites());
-
-                if(config.needClientAuth())
-                {
-                    sslServerSocket.setNeedClientAuth(true);
-                }
-                else if(config.wantClientAuth())
-                {
-                    sslServerSocket.setWantClientAuth(true);
-                }
-
-            }
-
-            _serverSocket.setReuseAddress(true);
-            _serverSocket.bind(address);
-        }
-
-
-        /**
-            Close the underlying ServerSocket if it has not already been closed.
-         */
-        public void close()
-        {
-            LOGGER.debug("Shutting down the Acceptor");
-            _closed = true;
-
-            if (!_serverSocket.isClosed())
-            {
-                try
-                {
-                    _serverSocket.close();
-                }
-                catch (IOException e)
-                {
-                    throw new TransportException(e);
-                }
-            }
-        }
-
-        private int getPort()
-        {
-            return _serverSocket.getLocalPort();
-        }
-
-        @Override
-        public void run()
-        {
-            try
-            {
-                while (!_closed)
-                {
-                    Socket socket = null;
-                    try
-                    {
-                        socket = _serverSocket.accept();
-
-                        ProtocolEngine engine = _factory.newProtocolEngine(socket.getRemoteSocketAddress());
-
-                        if(engine != null)
-                        {
-                            socket.setTcpNoDelay(_config.getTcpNoDelay());
-                            socket.setSoTimeout(1000 * HANSHAKE_TIMEOUT);
-
-                            final Integer sendBufferSize = _config.getSendBufferSize();
-                            final Integer receiveBufferSize = _config.getReceiveBufferSize();
-
-                            socket.setSendBufferSize(sendBufferSize);
-                            socket.setReceiveBufferSize(receiveBufferSize);
-
-
-                            final IdleTimeoutTicker ticker = new IdleTimeoutTicker(engine, TIMEOUT);
-                            NetworkConnection connection =
-                                    new IoNetworkConnection(socket, engine, sendBufferSize, receiveBufferSize, _timeout,
-                                                            ticker);
-
-                            connection.setMaxReadIdle(HANSHAKE_TIMEOUT);
-
-                            ticker.setConnection(connection);
-
-                            engine.setNetworkConnection(connection, connection.getSender());
-
-                            connection.start();
-                        }
-                        else
-                        {
-                            socket.close();
-                        }
-                    }
-                    catch(RuntimeException e)
-                    {
-                        LOGGER.error("Error in Acceptor thread on address " + _config.getAddress(), e);
-                        closeSocketIfNecessary(socket);
-                    }
-                    catch(IOException e)
-                    {
-                        if(!_closed)
-                        {
-                            LOGGER.error("Error in Acceptor thread on address " + _config.getAddress(), e);
-                            closeSocketIfNecessary(socket);
-                            try
-                            {
-                                //Delay to avoid tight spinning the loop during issues such as too many open files
-                                Thread.sleep(1000);
-                            }
-                            catch (InterruptedException ie)
-                            {
-                                LOGGER.debug("Stopping acceptor due to interrupt request");
-                                _closed = true;
-                            }
-                        }
-                    }
-                }
-            }
-            finally
-            {
-                if(LOGGER.isDebugEnabled())
-                {
-                    LOGGER.debug("Acceptor exiting, no new connections will be accepted on address " + _config.getAddress());
-                }
-            }
-        }
-
-        private void closeSocketIfNecessary(final Socket socket)
-        {
-            if(socket != null)
-            {
-                try
-                {
-                    socket.close();
-                }
-                catch (IOException e)
-                {
-                    LOGGER.debug("Exception while closing socket", e);
-                }
-            }
-        }
-
+        return new IoNetworkConnection(socket, engine, sendBufferSize, receiveBufferSize, timeout,
+                                ticker);
     }
 
 }
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java
index b52b59a..790583e 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java
@@ -31,7 +31,7 @@
 import javax.net.ssl.SSLSocket;
 
 import org.apache.qpid.thread.Threading;
-import org.apache.qpid.transport.Receiver;
+import org.apache.qpid.transport.ByteBufferReceiver;
 import org.apache.qpid.transport.TransportException;
 import org.apache.qpid.transport.network.Ticker;
 import org.apache.qpid.transport.util.Logger;
@@ -47,7 +47,7 @@
 
     private static final Logger log = Logger.get(IoReceiver.class);
 
-    private final Receiver<ByteBuffer> receiver;
+    private final ByteBufferReceiver receiver;
     private final int bufferSize;
     private final Socket socket;
     private final long timeout;
@@ -61,7 +61,7 @@
         shutdownBroken = SystemUtils.isWindows();
     }
 
-    public IoReceiver(Socket socket, Receiver<ByteBuffer> receiver, int bufferSize, long timeout)
+    public IoReceiver(Socket socket, ByteBufferReceiver receiver, int bufferSize, long timeout)
     {
         this.receiver = receiver;
         this.bufferSize = bufferSize;
@@ -78,7 +78,7 @@
             throw new RuntimeException("Error creating IOReceiver thread",e);
         }
         receiverThread.setDaemon(true);
-        receiverThread.setName(String.format("IoReceiver - %s", socket.getRemoteSocketAddress()));
+        receiverThread.setName(String.format("IoReceiver-%s", socket.getRemoteSocketAddress()));
     }
 
     public void initiate()
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoSender.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoSender.java
index 25222e5..cd01cdd 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoSender.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoSender.java
@@ -29,7 +29,7 @@
 import javax.net.ssl.SSLSocket;
 
 import org.apache.qpid.thread.Threading;
-import org.apache.qpid.transport.Sender;
+import org.apache.qpid.transport.ByteBufferSender;
 import org.apache.qpid.transport.SenderClosedException;
 import org.apache.qpid.transport.SenderException;
 import org.apache.qpid.transport.TransportException;
@@ -37,7 +37,7 @@
 import org.apache.qpid.util.SystemUtils;
 
 
-public final class IoSender implements Runnable, Sender<ByteBuffer>
+public final class IoSender implements Runnable, ByteBufferSender
 {
 
     private static final Logger log = Logger.get(IoSender.class);
@@ -97,7 +97,7 @@
         }
 
         senderThread.setDaemon(true);
-        senderThread.setName(String.format("IoSender - %s", _remoteSocketAddress));
+        senderThread.setName(String.format("IoSender-%s", _remoteSocketAddress));
     }
 
     public void initiate()
@@ -337,18 +337,6 @@
         }
     }
 
-    public void setIdleTimeout(int i)
-    {
-        try
-        {
-            socket.setSoTimeout(i);
-        }
-        catch (Exception e)
-        {
-            throw new SenderException(e);
-        }
-    }
-
     public void setReceiver(IoReceiver receiver)
     {
         _receiver = receiver;
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayer.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayer.java
index 51ef266..271135f 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayer.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayer.java
@@ -20,16 +20,14 @@
  */
 package org.apache.qpid.transport.network.security;
 
-import org.apache.qpid.transport.Receiver;
-import org.apache.qpid.transport.Sender;
-
-import java.nio.ByteBuffer;
+import org.apache.qpid.transport.ByteBufferReceiver;
+import org.apache.qpid.transport.ByteBufferSender;
 
 public interface SecurityLayer
 {
 
-    public Sender<ByteBuffer> sender(Sender<ByteBuffer> delegate);
-    public Receiver<ByteBuffer> receiver(Receiver<ByteBuffer> delegate);
+    public ByteBufferSender sender(ByteBufferSender delegate);
+    public ByteBufferReceiver receiver(ByteBufferReceiver delegate);
     public String getUserID();
 
 }
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayerFactory.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayerFactory.java
index 2a2f3d8..d25e97f 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayerFactory.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayerFactory.java
@@ -20,15 +20,13 @@
  */
 package org.apache.qpid.transport.network.security;
 
-import java.nio.ByteBuffer;
-
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLEngine;
 
 import org.apache.qpid.ssl.SSLContextFactory;
+import org.apache.qpid.transport.ByteBufferReceiver;
+import org.apache.qpid.transport.ByteBufferSender;
 import org.apache.qpid.transport.ConnectionSettings;
-import org.apache.qpid.transport.Receiver;
-import org.apache.qpid.transport.Sender;
 import org.apache.qpid.transport.TransportException;
 import org.apache.qpid.transport.network.security.sasl.SASLReceiver;
 import org.apache.qpid.transport.network.security.sasl.SASLSender;
@@ -110,14 +108,14 @@
 
         }
 
-        public Sender<ByteBuffer> sender(Sender<ByteBuffer> delegate)
+        public ByteBufferSender sender(ByteBufferSender delegate)
         {
             SSLSender sender = new SSLSender(_engine, _layer.sender(delegate), _sslStatus);
             sender.setHostname(_hostname);
             return sender;
         }
 
-        public Receiver<ByteBuffer> receiver(Receiver<ByteBuffer> delegate)
+        public ByteBufferReceiver receiver(ByteBufferReceiver delegate)
         {
             SSLReceiver receiver = new SSLReceiver(_engine, _layer.receiver(delegate), _sslStatus);
             receiver.setHostname(_hostname);
@@ -141,13 +139,13 @@
             _layer = layer;
         }
 
-        public SASLSender sender(Sender<ByteBuffer> delegate)
+        public SASLSender sender(ByteBufferSender delegate)
         {
             SASLSender sender = new SASLSender(_layer.sender(delegate));
             return sender;
         }
 
-        public SASLReceiver receiver(Receiver<ByteBuffer> delegate)
+        public SASLReceiver receiver(ByteBufferReceiver delegate)
         {
             SASLReceiver receiver = new SASLReceiver(_layer.receiver(delegate));
             return receiver;
@@ -169,12 +167,12 @@
         {
         }
 
-        public Sender<ByteBuffer> sender(Sender<ByteBuffer> delegate)
+        public ByteBufferSender sender(ByteBufferSender delegate)
         {
             return delegate;
         }
 
-        public Receiver<ByteBuffer> receiver(Receiver<ByteBuffer> delegate)
+        public ByteBufferReceiver receiver(ByteBufferReceiver delegate)
         {
             return delegate;
         }
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLReceiver.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLReceiver.java
index 59e9453..983e3bd 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLReceiver.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLReceiver.java
@@ -21,20 +21,21 @@
 package org.apache.qpid.transport.network.security.sasl;
 
 
-import org.apache.qpid.transport.Receiver;
+import java.nio.ByteBuffer;
+
+import javax.security.sasl.SaslException;
+
+import org.apache.qpid.transport.ByteBufferReceiver;
 import org.apache.qpid.transport.SenderException;
 import org.apache.qpid.transport.util.Logger;
 
-import javax.security.sasl.SaslException;
-import java.nio.ByteBuffer;
+public class SASLReceiver extends SASLEncryptor implements ByteBufferReceiver {
 
-public class SASLReceiver extends SASLEncryptor implements Receiver<ByteBuffer> {
-
-    private Receiver<ByteBuffer> delegate;
+    private ByteBufferReceiver delegate;
     private byte[] netData;
     private static final Logger log = Logger.get(SASLReceiver.class);
     
-    public SASLReceiver(Receiver<ByteBuffer> delegate)
+    public SASLReceiver(ByteBufferReceiver delegate)
     {
         this.delegate = delegate;
     }
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLSender.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLSender.java
index 098f2fb..335f899 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLSender.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/sasl/SASLSender.java
@@ -21,22 +21,24 @@
 package org.apache.qpid.transport.network.security.sasl;
 
 
-import org.apache.qpid.transport.Sender;
-import org.apache.qpid.transport.SenderException;
-import org.apache.qpid.transport.util.Logger;
-
-import javax.security.sasl.SaslException;
 import java.nio.ByteBuffer;
 import java.util.concurrent.atomic.AtomicBoolean;
 
-public class SASLSender extends SASLEncryptor implements Sender<ByteBuffer> {
+import javax.security.sasl.SaslException;
 
-    private Sender<ByteBuffer> delegate;
+import org.apache.qpid.transport.ByteBufferSender;
+import org.apache.qpid.transport.SenderException;
+import org.apache.qpid.transport.util.Logger;
+
+public class SASLSender extends SASLEncryptor implements ByteBufferSender
+{
+
+    private ByteBufferSender delegate;
     private byte[] appData;
     private final AtomicBoolean closed = new AtomicBoolean(false);
     private static final Logger log = Logger.get(SASLSender.class);
     
-    public SASLSender(Sender<ByteBuffer> delegate)
+    public SASLSender(ByteBufferSender delegate)
     {
         this.delegate = delegate;
         log.debug("SASL Sender enabled");
@@ -103,11 +105,6 @@
         }        
     }
 
-    public void setIdleTimeout(int i) 
-    {
-        delegate.setIdleTimeout(i);
-    }
-    
     public void securityLayerEstablished()
     {
         appData = new byte[getSendBuffSize()];
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLBufferingSender.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLBufferingSender.java
index 24f95d7..e69de29 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLBufferingSender.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLBufferingSender.java
@@ -1,274 +0,0 @@
-/*
- * 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.transport.network.security.ssl;
-
-import java.nio.ByteBuffer;
-import java.util.concurrent.atomic.AtomicBoolean;
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLEngineResult;
-import javax.net.ssl.SSLEngineResult.HandshakeStatus;
-import javax.net.ssl.SSLEngineResult.Status;
-import javax.net.ssl.SSLException;
-import org.apache.qpid.transport.Sender;
-import org.apache.qpid.transport.SenderException;
-import org.apache.qpid.transport.network.security.SSLStatus;
-import org.apache.qpid.transport.util.Logger;
-
-public class SSLBufferingSender implements Sender<ByteBuffer>
-{
-    private static final Logger log = Logger.get(SSLBufferingSender.class);
-    private static final ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.allocate(0);
-
-    private final Sender<ByteBuffer> delegate;
-    private final SSLEngine engine;
-    private final int sslBufSize;
-    private final ByteBuffer netData;
-    private final SSLStatus _sslStatus;
-
-    private String _hostname;
-
-    private final AtomicBoolean closed = new AtomicBoolean(false);
-    private ByteBuffer _appData = EMPTY_BYTE_BUFFER;
-
-
-    public SSLBufferingSender(SSLEngine engine, Sender<ByteBuffer> delegate, SSLStatus sslStatus)
-    {
-        this.engine = engine;
-        this.delegate = delegate;
-        sslBufSize = engine.getSession().getPacketBufferSize();
-        netData = ByteBuffer.allocate(sslBufSize);
-        _sslStatus = sslStatus;
-    }
-
-    public void setHostname(String hostname)
-    {
-        _hostname = hostname;
-    }
-
-    public void close()
-    {
-        if (!closed.getAndSet(true))
-        {
-            if (engine.isOutboundDone())
-            {
-                return;
-            }
-            log.debug("Closing SSL connection");
-            doSend();
-            engine.closeOutbound();
-            try
-            {
-                tearDownSSLConnection();
-            }
-            catch(Exception e)
-            {
-                throw new SenderException("Error closing SSL connection",e);
-            }
-
-
-            synchronized(_sslStatus.getSslLock())
-            {
-                while (!engine.isOutboundDone())
-                {
-                    try
-                    {
-                        _sslStatus.getSslLock().wait();
-                    }
-                    catch(InterruptedException e)
-                    {
-                        // pass
-                    }
-
-                }
-            }
-            delegate.close();
-        }
-    }
-
-    private void tearDownSSLConnection() throws Exception
-    {
-        SSLEngineResult result = engine.wrap(ByteBuffer.allocate(0), netData);
-        Status status = result.getStatus();
-        int read   = result.bytesProduced();
-        while (status != Status.CLOSED)
-        {
-            if (status == Status.BUFFER_OVERFLOW)
-            {
-                netData.clear();
-            }
-            if(read > 0)
-            {
-                int limit = netData.limit();
-                netData.limit(netData.position());
-                netData.position(netData.position() - read);
-
-                ByteBuffer data = netData.slice();
-
-                netData.limit(limit);
-                netData.position(netData.position() + read);
-
-                delegate.send(data);
-                flush();
-            }
-            result = engine.wrap(ByteBuffer.allocate(0), netData);
-            status = result.getStatus();
-            read   = result.bytesProduced();
-        }
-    }
-
-    public void flush()
-    {
-        delegate.flush();
-    }
-
-    public void send()
-    {
-        if(!closed.get())
-        {
-            doSend();
-        }
-    }
-
-    public synchronized void send(ByteBuffer appData)
-    {
-        boolean buffered;
-        if(buffered = _appData.hasRemaining())
-        {
-            ByteBuffer newBuf = ByteBuffer.allocate(_appData.remaining()+appData.remaining());
-            newBuf.put(_appData);
-            newBuf.put(appData);
-            newBuf.flip();
-            _appData = newBuf;
-        }
-        if (closed.get())
-        {
-            throw new SenderException("SSL Sender is closed");
-        }
-        doSend();
-        if(!appData.hasRemaining())
-        {
-            _appData = EMPTY_BYTE_BUFFER;
-        }
-        else if(!buffered)
-        {
-            _appData = ByteBuffer.allocate(appData.remaining());
-            _appData.put(appData);
-            _appData.flip();
-        }
-    }
-
-    private synchronized void doSend()
-    {
-
-        HandshakeStatus handshakeStatus;
-        Status status;
-
-        while((_appData.hasRemaining() || engine.getHandshakeStatus() == HandshakeStatus.NEED_WRAP)
-              && !_sslStatus.getSslErrorFlag())
-        {
-            int read = 0;
-            try
-            {
-                SSLEngineResult result = engine.wrap(_appData, netData);
-                read   = result.bytesProduced();
-                status = result.getStatus();
-                handshakeStatus = result.getHandshakeStatus();
-            }
-            catch(SSLException e)
-            {
-                // Should this set _sslError??
-                throw new SenderException("SSL, Error occurred while encrypting data",e);
-            }
-
-            if(read > 0)
-            {
-                int limit = netData.limit();
-                netData.limit(netData.position());
-                netData.position(netData.position() - read);
-
-                ByteBuffer data = netData.slice();
-
-                netData.limit(limit);
-                netData.position(netData.position() + read);
-
-                delegate.send(data);
-            }
-
-            switch(status)
-            {
-                case CLOSED:
-                    throw new SenderException("SSLEngine is closed");
-
-                case BUFFER_OVERFLOW:
-                    netData.clear();
-                    continue;
-
-                case OK:
-                    break; // do nothing
-
-                default:
-                    throw new IllegalStateException("SSLReceiver: Invalid State " + status);
-            }
-
-            switch (handshakeStatus)
-            {
-                case NEED_WRAP:
-                    if (netData.hasRemaining())
-                    {
-                        continue;
-                    }
-
-                case NEED_TASK:
-                    doTasks();
-                    break;
-
-                case NEED_UNWRAP:
-                    flush();
-                    return;
-
-                case FINISHED:
-                    if (_hostname != null)
-                    {
-                        SSLUtil.verifyHostname(engine, _hostname);
-                    }
-
-                case NOT_HANDSHAKING:
-                    break; //do  nothing
-
-                default:
-                    throw new IllegalStateException("SSLSender: Invalid State " + status);
-            }
-
-        }
-    }
-
-    private void doTasks()
-    {
-        Runnable runnable;
-        while ((runnable = engine.getDelegatedTask()) != null) {
-            runnable.run();
-        }
-    }
-
-    public void setIdleTimeout(int i)
-    {
-        delegate.setIdleTimeout(i);
-    }
-}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLReceiver.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLReceiver.java
index 8e1395a..49e4ad6 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLReceiver.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLReceiver.java
@@ -28,16 +28,16 @@
 import javax.net.ssl.SSLEngineResult.Status;
 import javax.net.ssl.SSLException;
 
-import org.apache.qpid.transport.Receiver;
+import org.apache.qpid.transport.ByteBufferReceiver;
 import org.apache.qpid.transport.TransportException;
 import org.apache.qpid.transport.network.security.SSLStatus;
 import org.apache.qpid.transport.util.Logger;
 
-public class SSLReceiver implements Receiver<ByteBuffer>
+public class SSLReceiver implements ByteBufferReceiver
 {
     private static final Logger log = Logger.get(SSLReceiver.class);
 
-    private final Receiver<ByteBuffer> delegate;
+    private final ByteBufferReceiver delegate;
     private final SSLEngine engine;
     private final int sslBufSize;
     private final ByteBuffer localBuffer;
@@ -47,7 +47,7 @@
 
     private String _hostname;
 
-    public SSLReceiver(final SSLEngine engine, final Receiver<ByteBuffer> delegate, final SSLStatus sslStatus)
+    public SSLReceiver(final SSLEngine engine, final ByteBufferReceiver delegate, final SSLStatus sslStatus)
     {
         this.engine = engine;
         this.delegate = delegate;
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLSender.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLSender.java
index 53bd7e4..3d133cb 100644
--- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLSender.java
+++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLSender.java
@@ -19,24 +19,25 @@
  */
 package org.apache.qpid.transport.network.security.ssl;
 
-import org.apache.qpid.transport.Sender;
-import org.apache.qpid.transport.SenderException;
-import org.apache.qpid.transport.network.security.SSLStatus;
-import org.apache.qpid.transport.util.Logger;
+import java.nio.ByteBuffer;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import javax.net.ssl.SSLEngine;
 import javax.net.ssl.SSLEngineResult;
 import javax.net.ssl.SSLEngineResult.HandshakeStatus;
 import javax.net.ssl.SSLEngineResult.Status;
 import javax.net.ssl.SSLException;
-import java.nio.ByteBuffer;
-import java.util.concurrent.atomic.AtomicBoolean;
 
-public class SSLSender implements Sender<ByteBuffer>
+import org.apache.qpid.transport.ByteBufferSender;
+import org.apache.qpid.transport.SenderException;
+import org.apache.qpid.transport.network.security.SSLStatus;
+import org.apache.qpid.transport.util.Logger;
+
+public class SSLSender implements ByteBufferSender
 {
     private static final Logger log = Logger.get(SSLSender.class);
 
-    private final Sender<ByteBuffer> delegate;
+    private final ByteBufferSender delegate;
     private final SSLEngine engine;
     private final int sslBufSize;
     private final ByteBuffer netData;
@@ -48,7 +49,7 @@
     private final AtomicBoolean closed = new AtomicBoolean(false);
 
 
-    public SSLSender(SSLEngine engine, Sender<ByteBuffer> delegate, SSLStatus sslStatus)
+    public SSLSender(SSLEngine engine, ByteBufferSender delegate, SSLStatus sslStatus)
     {
         this.engine = engine;
         this.delegate = delegate;
@@ -264,8 +265,4 @@
         }
     }
 
-    public void setIdleTimeout(int i)
-    {
-        delegate.setIdleTimeout(i);
-    }
 }
diff --git a/qpid/java/common/src/test/java/org/apache/qpid/transport/network/TransportTest.java b/qpid/java/common/src/test/java/org/apache/qpid/transport/network/TransportTest.java
index 3071594..3da2a03 100644
--- a/qpid/java/common/src/test/java/org/apache/qpid/transport/network/TransportTest.java
+++ b/qpid/java/common/src/test/java/org/apache/qpid/transport/network/TransportTest.java
@@ -21,16 +21,16 @@
 package org.apache.qpid.transport.network;
 
 
-import java.nio.ByteBuffer;
+import java.util.Set;
 
 import javax.net.ssl.SSLContext;
 
 import org.apache.qpid.framing.ProtocolVersion;
 import org.apache.qpid.protocol.ProtocolEngineFactory;
 import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.transport.ByteBufferReceiver;
 import org.apache.qpid.transport.ConnectionSettings;
 import org.apache.qpid.transport.NetworkTransportConfiguration;
-import org.apache.qpid.transport.Receiver;
 import org.apache.qpid.transport.TransportException;
 import org.apache.qpid.transport.network.io.IoNetworkTransport;
 
@@ -129,7 +129,7 @@
         }
 
         public NetworkConnection connect(ConnectionSettings settings,
-                                         Receiver<ByteBuffer> delegate,
+                                         ByteBufferReceiver delegate,
                                          TransportActivity transportActivity)
         {
             throw new UnsupportedOperationException();
@@ -150,7 +150,9 @@
         }
 
         public void accept(NetworkTransportConfiguration config,
-                           ProtocolEngineFactory factory, SSLContext sslContext)
+                           ProtocolEngineFactory factory,
+                           SSLContext sslContext,
+                           final Set<TransportEncryption> encryptionSet)
         {
             throw new UnsupportedOperationException();
         }
diff --git a/qpid/java/common/src/test/java/org/apache/qpid/transport/network/io/IdleTimeoutTickerTest.java b/qpid/java/common/src/test/java/org/apache/qpid/transport/network/io/IdleTimeoutTickerTest.java
index a445cff..6972443 100644
--- a/qpid/java/common/src/test/java/org/apache/qpid/transport/network/io/IdleTimeoutTickerTest.java
+++ b/qpid/java/common/src/test/java/org/apache/qpid/transport/network/io/IdleTimeoutTickerTest.java
@@ -21,14 +21,12 @@
 
 package org.apache.qpid.transport.network.io;
 
-import junit.framework.TestCase;
-
 import java.net.SocketAddress;
-import java.nio.ByteBuffer;
 import java.security.Principal;
 
-import org.apache.qpid.test.utils.QpidTestCase;
-import org.apache.qpid.transport.Sender;
+import junit.framework.TestCase;
+
+import org.apache.qpid.transport.ByteBufferSender;
 import org.apache.qpid.transport.network.NetworkConnection;
 import org.apache.qpid.transport.network.TransportActivity;
 
@@ -193,7 +191,7 @@
     //-------------------------------------------------------------------------
 
     @Override
-    public Sender<ByteBuffer> getSender()
+    public ByteBufferSender getSender()
     {
         return null;
     }
diff --git a/qpid/java/common/src/test/java/org/apache/qpid/transport/network/io/IoAcceptor.java b/qpid/java/common/src/test/java/org/apache/qpid/transport/network/io/IoAcceptor.java
index bb864cd..67d360f 100644
--- a/qpid/java/common/src/test/java/org/apache/qpid/transport/network/io/IoAcceptor.java
+++ b/qpid/java/common/src/test/java/org/apache/qpid/transport/network/io/IoAcceptor.java
@@ -20,16 +20,15 @@
  */
 package org.apache.qpid.transport.network.io;
 
-import org.apache.log4j.Logger;
-import org.apache.qpid.transport.Binding;
-import org.apache.qpid.transport.TransportException;
-
 import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.net.ServerSocket;
 import java.net.Socket;
 import java.net.SocketAddress;
-import java.nio.ByteBuffer;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.transport.Binding;
 
 
 /**
@@ -44,9 +43,9 @@
     private volatile boolean _closed = false;
 
     private ServerSocket socket;
-    private Binding<E,ByteBuffer> binding;
+    private Binding<E> binding;
 
-    public IoAcceptor(SocketAddress address, Binding<E,ByteBuffer> binding)
+    public IoAcceptor(SocketAddress address, Binding<E> binding)
         throws IOException
     {
         socket = new ServerSocket();
@@ -70,7 +69,7 @@
         }
     }
 
-    public IoAcceptor(String host, int port, Binding<E,ByteBuffer> binding)
+    public IoAcceptor(String host, int port, Binding<E> binding)
         throws IOException
     {
         this(new InetSocketAddress(host, port), binding);
diff --git a/qpid/java/common/src/test/java/org/apache/qpid/transport/network/io/IoTransport.java b/qpid/java/common/src/test/java/org/apache/qpid/transport/network/io/IoTransport.java
index f74051a..4b5b444 100644
--- a/qpid/java/common/src/test/java/org/apache/qpid/transport/network/io/IoTransport.java
+++ b/qpid/java/common/src/test/java/org/apache/qpid/transport/network/io/IoTransport.java
@@ -20,10 +20,9 @@
 package org.apache.qpid.transport.network.io;
 
 import java.net.Socket;
-import java.nio.ByteBuffer;
 
 import org.apache.qpid.transport.Binding;
-import org.apache.qpid.transport.Sender;
+import org.apache.qpid.transport.ByteBufferSender;
 import org.apache.qpid.transport.util.Logger;
 
 /**
@@ -48,18 +47,18 @@
         ("amqj.sendBufferSize", DEFAULT_READ_WRITE_BUFFER_SIZE);
 
     private Socket socket;
-    private Sender<ByteBuffer> sender;
+    private ByteBufferSender sender;
     private E endpoint;
     private IoReceiver receiver;
     private long timeout = 60000;
 
-    IoTransport(Socket socket, Binding<E,ByteBuffer> binding)
+    IoTransport(Socket socket, Binding<E> binding)
     {
         this.socket = socket;
         setupTransport(socket, binding);
     }
 
-    private void setupTransport(Socket socket, Binding<E, ByteBuffer> binding)
+    private void setupTransport(Socket socket, Binding<E> binding)
     {
         IoSender ios = new IoSender(socket, 2*writeBufferSize, timeout);
         ios.initiate();
@@ -73,7 +72,7 @@
         ios.setReceiver(this.receiver);
     }
 
-    public Sender<ByteBuffer> getSender()
+    public ByteBufferSender getSender()
     {
         return sender;
     }
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java
index a76f79f..9e8f0d1 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java
@@ -21,16 +21,16 @@
 package org.apache.qpid.test.utils;
 
 import java.security.PrivilegedAction;
-import java.util.Map;
 import java.util.Set;
 
+import javax.security.auth.Subject;
+
 import org.apache.log4j.Logger;
 
 import org.apache.qpid.server.Broker;
 import org.apache.qpid.server.BrokerOptions;
 import org.apache.qpid.server.security.SecurityManager;
-
-import javax.security.auth.Subject;
+import org.apache.qpid.server.util.Action;
 
 public class InternalBrokerHolder implements BrokerHolder
 {
@@ -50,7 +50,14 @@
     {
         LOGGER.info("Starting internal broker (same JVM)");
 
-        _broker = new Broker();
+        _broker = new Broker(new Action<Integer>()
+        {
+            @Override
+            public void performAction(final Integer object)
+            {
+                _broker = null;
+            }
+        });
         _broker.startup(options);
     }
 
@@ -63,7 +70,10 @@
             @Override
             public Object run()
             {
-                _broker.shutdown();
+                if(_broker != null)
+                {
+                    _broker.shutdown();
+                }
                 return null;
             }
 
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/client/AMQQueueDeferredOrderingTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/client/AMQQueueDeferredOrderingTest.java
index 3025414..0acdd25 100644
--- a/qpid/java/systests/src/test/java/org/apache/qpid/client/AMQQueueDeferredOrderingTest.java
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/client/AMQQueueDeferredOrderingTest.java
@@ -20,12 +20,6 @@
  */
 package org.apache.qpid.client;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
-
 import javax.jms.Connection;
 import javax.jms.Message;
 import javax.jms.MessageConsumer;
@@ -33,13 +27,19 @@
 import javax.jms.Session;
 import javax.jms.TextMessage;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+
 public class AMQQueueDeferredOrderingTest extends QpidBrokerTestCase
 {
     private Connection con;
     private Session session;
     private AMQQueue queue;
     private MessageConsumer consumer;
-    private int numMessages;
+    private int _numMessages;
 
     private static final Logger _logger = LoggerFactory.getLogger(AMQQueueDeferredOrderingTest.class);
 
@@ -86,7 +86,7 @@
     {
         super.setUp();
 
-        numMessages = isBrokerStorePersistent() ? 300 : 1000;
+        _numMessages = isBrokerStorePersistent() ? 300 : 1000;
 
         _logger.info("Create Connection");
         con = getConnection();
@@ -106,30 +106,31 @@
 
         // Setup initial messages
         _logger.info("Creating first producer thread");
-        producerThread = new ASyncProducer(queue, 0, numMessages / 2);
+        producerThread = new ASyncProducer(queue, 0, _numMessages / 2);
         producerThread.start();
         // Wait for them to be done
         producerThread.join();
 
         // Setup second set of messages to produce while we consume
         _logger.info("Creating second producer thread");
-        producerThread = new ASyncProducer(queue, numMessages / 2, numMessages);
+        producerThread = new ASyncProducer(queue, _numMessages / 2, _numMessages);
         producerThread.start();
 
         // Start consuming and checking they're in order
         _logger.info("Consuming messages");
-        for (int i = 0; i < numMessages; i++)
+        for (int i = 0; i < _numMessages; i++)
         {
             Message msg = consumer.receive(3000);
+
             assertNotNull("Message " + i + " should not be null", msg);
             assertTrue("Message " + i + " should be a text message", msg instanceof TextMessage);
-            assertEquals("Message content " + i + "does not match expected", Integer.toString(i), ((TextMessage) msg).getText());
+            assertEquals("Message content " + i + " does not match expected", Integer.toString(i), ((TextMessage) msg).getText());
         }
     }
 
     protected void tearDown() throws Exception
     {
-        _logger.info("Interuptting producer thread");
+        _logger.info("Interrupting producer thread");
         producerThread.interrupt();
         _logger.info("Closing connection");
         con.close();
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/client/AsynchMessageListenerTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/client/AsynchMessageListenerTest.java
index a13bf71..74b1f8a 100644
--- a/qpid/java/systests/src/test/java/org/apache/qpid/client/AsynchMessageListenerTest.java
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/client/AsynchMessageListenerTest.java
@@ -70,6 +70,9 @@
 
     }
 
+
+
+
     public void testMessageListener() throws Exception
     {
         CountingMessageListener countingMessageListener = new CountingMessageListener(MSG_COUNT);
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/client/ssl/SSLTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/client/ssl/SSLTest.java
index 72dea9b..5357f4b 100644
--- a/qpid/java/systests/src/test/java/org/apache/qpid/client/ssl/SSLTest.java
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/client/ssl/SSLTest.java
@@ -290,7 +290,8 @@
         ByteArrayOutputStream bout = new ByteArrayOutputStream();
         e.printStackTrace(new PrintStream(bout));
         String strace = bout.toString();
-        assertTrue("Correct exception not thrown", strace.contains(expectedString));
+        assertTrue("Correct exception not thrown, expecting : " + expectedString + " got : " +e,
+                   strace.contains(expectedString));
     }
 
     public void testVerifyLocalHost() throws Exception
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactoryTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactoryTest.java
index 007772e..a1e30ac 100644
--- a/qpid/java/systests/src/test/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactoryTest.java
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactoryTest.java
@@ -33,7 +33,6 @@
 import java.util.Iterator;
 import java.util.Set;
 
-import org.apache.qpid.protocol.ServerProtocolEngine;
 import org.apache.qpid.server.model.Broker;
 import org.apache.qpid.server.model.Port;
 import org.apache.qpid.server.model.Protocol;
@@ -41,7 +40,7 @@
 import org.apache.qpid.server.util.BrokerTestHelper;
 import org.apache.qpid.server.virtualhost.VirtualHostImpl;
 import org.apache.qpid.test.utils.QpidTestCase;
-import org.apache.qpid.transport.Sender;
+import org.apache.qpid.transport.ByteBufferSender;
 import org.apache.qpid.transport.network.NetworkConnection;
 
 public class MultiVersionProtocolEngineFactoryTest extends QpidTestCase
@@ -161,7 +160,7 @@
 
         when(port.getContextValue(eq(Long.class),eq(Port.CONNECTION_MAXIMUM_AUTHENTICATION_DELAY))).thenReturn(10000l);
         MultiVersionProtocolEngineFactory factory =
-            new MultiVersionProtocolEngineFactory(_broker, null, false, false, protocols, null, port,
+            new MultiVersionProtocolEngineFactory(_broker, protocols, null, port,
                     org.apache.qpid.server.model.Transport.TCP);
 
         //create a dummy to retrieve the 'current' ID number
@@ -215,7 +214,7 @@
 
         try
         {
-            new MultiVersionProtocolEngineFactory(_broker, null, false, false, versions, Protocol.AMQP_0_9, null,
+            new MultiVersionProtocolEngineFactory(_broker, versions, Protocol.AMQP_0_9, null,
                     org.apache.qpid.server.model.Transport.TCP);
             fail("should not have been allowed to create the factory");
         }
@@ -230,16 +229,12 @@
         private String _remoteHost = "127.0.0.1";
         private String _localHost = "127.0.0.1";
         private int _port = 1;
-        private final Sender<ByteBuffer> _sender;
+        private final ByteBufferSender _sender;
 
         public TestNetworkConnection()
         {
-            _sender = new Sender<ByteBuffer>()
+            _sender = new ByteBufferSender()
             {
-                public void setIdleTimeout(int i)
-                {
-                }
-
                 public void send(ByteBuffer msg)
                 {
                 }
@@ -300,7 +295,7 @@
         }
 
         @Override
-        public Sender<ByteBuffer> getSender()
+        public ByteBufferSender getSender()
         {
             return _sender;
         }
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/server/store/VirtualHostMessageStoreTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/server/store/VirtualHostMessageStoreTest.java
index 32de061..b243769 100644
--- a/qpid/java/systests/src/test/java/org/apache/qpid/server/store/VirtualHostMessageStoreTest.java
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/server/store/VirtualHostMessageStoreTest.java
@@ -386,7 +386,7 @@
         assertEquals("Incorrect number of exchanges registered after second recovery",
                 origExchangeCount,  _virtualHost.getExchanges().size());
         assertNull("Durable exchange was not removed:" + directExchangeName,
-                _virtualHost.getExchange(directExchangeName));
+                   _virtualHost.getExchange(directExchangeName));
     }
 
     /**
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java
index 67af3e1..ee9f207 100644
--- a/qpid/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java
@@ -23,13 +23,7 @@
 import java.util.Iterator;
 import java.util.List;
 
-import javax.jms.Connection;
-import javax.jms.Destination;
-import javax.jms.JMSException;
-import javax.jms.Message;
-import javax.jms.MessageConsumer;
-import javax.jms.Queue;
-import javax.jms.Session;
+import javax.jms.*;
 import javax.management.JMException;
 import javax.management.openmbean.CompositeData;
 import javax.management.openmbean.CompositeDataSupport;
@@ -74,6 +68,38 @@
         }
     }
 
+    public void testManagementClosesConnection() throws Exception
+    {
+        assertEquals("Expected no managed connections", 0, getManagedConnections().size());
+
+        _connection = getConnection();
+        assertEquals("Expected one managed connection", 1, getManagedConnections().size());
+
+
+        ManagedConnection managedConnection = getManagedConnections().get(0);
+
+        managedConnection.closeConnection();
+
+        assertEquals("Expected no managed connections", 0, getManagedConnections().size());
+
+        /*
+        try
+        {
+
+            _connection.start();
+            fail("Exception not thrown");
+        }
+        catch (javax.jms.IllegalStateException ise)
+        {
+            ise.printStackTrace();
+            // PASS
+        }*/
+
+    }
+
+
+
+
     public void testNumberOfManagedConnectionsMatchesNumberOfClientConnections() throws Exception
     {
         assertEquals("Expected no managed connections", 0, getManagedConnections().size());
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/LogRecordsRestTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/LogRecordsRestTest.java
index 4d06c7b..4ca3b2b 100644
--- a/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/LogRecordsRestTest.java
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/systest/rest/LogRecordsRestTest.java
@@ -36,7 +36,6 @@
         assertNotNull("Message id cannot be null", record.get("id"));
         assertNotNull("Message timestamp cannot be null", record.get("timestamp"));
         assertEquals("Unexpected log level", "INFO", record.get("level"));
-        assertEquals("Unexpected thread", "main", record.get("thread"));
         assertEquals("Unexpected logger", "qpid.message.broker.ready", record.get("logger"));
     }
 
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java
index 6b6b4a7..8a4e227 100644
--- a/qpid/java/systests/src/test/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/test/client/QueueBrowserAutoAckTest.java
@@ -148,7 +148,6 @@
         assertEquals("Session reports Queue expectedDepth not as expected", expectedDepth, queueDepth);
 
 
-
         // Browse the queue to get a second opinion
         int msgCount = 0;
         Enumeration msgs = queueBrowser.getEnumeration();
@@ -268,7 +267,7 @@
         //validate all browsers get right message count.
         for (int count = 0; count < browserEnumerationCount; count++)
         {
-            assertEquals(msgCount[count], expectedMessages);
+            assertEquals("Unexpected count for browser " + count, expectedMessages, msgCount[count]);
         }
 
         try
@@ -317,7 +316,7 @@
         //Close this new connection
         connection.close();
 
-        _logger.info("All messages recevied from queue");
+        _logger.info("All messages received from queue");
 
         //ensure no message left.
         checkQueueDepth(0);
@@ -344,7 +343,7 @@
 
     /*
     * Test Messages Remain on Queue
-    * Create a queu and send messages to it. Browse them and then receive them all to verify they were still there
+    * Create a queue and send messages to it. Browse them and then receive them all to verify they were still there
     *
     */
     public void testQueueBrowserMsgsRemainOnQueue() throws Exception
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java
index 3ffa73b..54e5a5c 100644
--- a/qpid/java/systests/src/test/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java
@@ -32,7 +32,7 @@
 import org.apache.qpid.client.protocol.AMQProtocolSession;
 import org.apache.qpid.framing.AMQShortString;
 import org.apache.qpid.test.utils.QpidBrokerTestCase;
-import org.apache.qpid.transport.Sender;
+import org.apache.qpid.transport.ByteBufferSender;
 import org.apache.qpid.transport.network.NetworkConnection;
 
 public class AMQProtocolSessionTest extends QpidBrokerTestCase
@@ -107,18 +107,13 @@
         private String _localHost = "127.0.0.1";
         private int _port = 1;
         private SocketAddress _localAddress = null;
-        private final Sender<ByteBuffer> _sender;
+        private final ByteBufferSender _sender;
 
         public TestNetworkConnection()
         {
-            _sender = new Sender<ByteBuffer>()
+            _sender = new ByteBufferSender()
             {
 
-                public void setIdleTimeout(int i)
-                {
-
-                }
-
                 public void send(ByteBuffer msg)
                 {
 
@@ -186,7 +181,7 @@
             _localAddress = address;
         }
 
-        public Sender<ByteBuffer> getSender()
+        public ByteBufferSender getSender()
         {
             return _sender;
         }
diff --git a/qpid/java/systests/src/test/java/org/apache/qpid/transport/MaxFrameSizeTest.java b/qpid/java/systests/src/test/java/org/apache/qpid/transport/MaxFrameSizeTest.java
index f762038..5928a41 100644
--- a/qpid/java/systests/src/test/java/org/apache/qpid/transport/MaxFrameSizeTest.java
+++ b/qpid/java/systests/src/test/java/org/apache/qpid/transport/MaxFrameSizeTest.java
@@ -313,14 +313,10 @@
                                   _maxFrameSize,
                                   actualHeartbeatInterval);
 
-            int idleTimeout = (int)(actualHeartbeatInterval * 1000 * heartbeatTimeoutFactor);
             conn.getNetworkConnection().setMaxReadIdle((int)(actualHeartbeatInterval*heartbeatTimeoutFactor));
             conn.getNetworkConnection().setMaxWriteIdle(actualHeartbeatInterval);
             conn.setMaxFrameSize(_maxFrameSize);
 
-
-            conn.setIdleTimeout(idleTimeout);
-
             int channelMax = tune.getChannelMax();
             conn.setChannelMax(channelMax == 0 ? Connection.MAX_CHANNEL_MAX : channelMax);
 
diff --git a/qpid/java/test-profiles/JavaExcludes b/qpid/java/test-profiles/JavaExcludes
index cafb1d5..95de7de 100644
--- a/qpid/java/test-profiles/JavaExcludes
+++ b/qpid/java/test-profiles/JavaExcludes
@@ -26,3 +26,11 @@
 
 //QPID-4153 Messages causing a runtime selector error should be dead-lettered (or something similar)
 org.apache.qpid.test.client.message.SelectorTest#testRuntimeSelectorError
+
+
+org.apache.qpid.server.protocol.v0_8.AckTest#*
+org.apache.qpid.server.protocol.v0_8.AcknowledgeTest#*
+org.apache.qpid.server.protocol.v0_8.AMQChannelTest#*
+org.apache.qpid.server.protocol.v0_8.QueueBrowserUsesNoAckTest#*
+org.apache.qpid.server.protocol.v0_8.MaxChannelsTest#*
+
diff --git a/qpid/java/test-profiles/JavaTransientExcludes b/qpid/java/test-profiles/JavaTransientExcludes
index 70056d6..3397c7f 100644
--- a/qpid/java/test-profiles/JavaTransientExcludes
+++ b/qpid/java/test-profiles/JavaTransientExcludes
@@ -47,6 +47,7 @@
 org.apache.qpid.server.store.berkeleydb.*
 org.apache.qpid.server.store.berkeleydb.replication.*
 org.apache.qpid.server.store.berkeleydb.upgrade.*
+org.apache.qpid.server.virtualhostnode.berkeleydb.*
 
 org.apache.qpid.systest.management.jmx.QueueManagementTest#testAlternateExchangeSurvivesRestart
 org.apache.qpid.systest.management.jmx.QueueManagementTest#testQueueDescriptionSurvivesRestart