You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by ta...@apache.org on 2017/05/11 17:17:00 UTC

activemq git commit: AMQ-6672 Use a dynamic proxy to create unmodifiable types

Repository: activemq
Updated Branches:
  refs/heads/master eb1a3eb77 -> fddbac2b8


AMQ-6672 Use a dynamic proxy to create unmodifiable types

Use a dynamic proxy instead of hand-crafted wrappers around proton
types to prevent access to mutating methods in tests that could
inadvertantly change the state outside the connection thread.


Project: http://git-wip-us.apache.org/repos/asf/activemq/repo
Commit: http://git-wip-us.apache.org/repos/asf/activemq/commit/fddbac2b
Tree: http://git-wip-us.apache.org/repos/asf/activemq/tree/fddbac2b
Diff: http://git-wip-us.apache.org/repos/asf/activemq/diff/fddbac2b

Branch: refs/heads/master
Commit: fddbac2b8a6b2686c0305e3e24a8ac549cc9e345
Parents: eb1a3eb
Author: Timothy Bish <ta...@gmail.com>
Authored: Wed May 10 18:16:55 2017 -0400
Committer: Timothy Bish <ta...@gmail.com>
Committed: Thu May 11 13:14:39 2017 -0400

----------------------------------------------------------------------
 .../transport/amqp/client/AmqpConnection.java   |   4 +-
 .../transport/amqp/client/AmqpMessage.java      |   4 +-
 .../transport/amqp/client/AmqpReceiver.java     |   4 +-
 .../transport/amqp/client/AmqpSender.java       |   5 +-
 .../transport/amqp/client/AmqpSession.java      |   4 +-
 .../client/util/UnmodifiableConnection.java     | 202 ------------
 .../amqp/client/util/UnmodifiableDelivery.java  | 173 ----------
 .../amqp/client/util/UnmodifiableLink.java      | 322 -------------------
 .../amqp/client/util/UnmodifiableProxy.java     | 167 ++++++++++
 .../amqp/client/util/UnmodifiableReceiver.java  |  65 ----
 .../amqp/client/util/UnmodifiableSender.java    |  51 ---
 .../amqp/client/util/UnmodifiableSession.java   | 197 ------------
 .../amqp/client/util/UnmodifiableTransport.java | 274 ----------------
 .../amqp/interop/AmqpConnectionsTest.java       |  27 ++
 .../transport/amqp/interop/AmqpSessionTest.java |  35 ++
 15 files changed, 239 insertions(+), 1295 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/activemq/blob/fddbac2b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/AmqpConnection.java
----------------------------------------------------------------------
diff --git a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/AmqpConnection.java b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/AmqpConnection.java
index c252d1f..b3ec0ae 100644
--- a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/AmqpConnection.java
+++ b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/AmqpConnection.java
@@ -39,7 +39,7 @@ import org.apache.activemq.transport.amqp.client.util.AsyncResult;
 import org.apache.activemq.transport.amqp.client.util.ClientFuture;
 import org.apache.activemq.transport.amqp.client.util.IdGenerator;
 import org.apache.activemq.transport.amqp.client.util.NoOpAsyncResult;
-import org.apache.activemq.transport.amqp.client.util.UnmodifiableConnection;
+import org.apache.activemq.transport.amqp.client.util.UnmodifiableProxy;
 import org.apache.qpid.proton.amqp.Symbol;
 import org.apache.qpid.proton.engine.Collector;
 import org.apache.qpid.proton.engine.Connection;
@@ -413,7 +413,7 @@ public class AmqpConnection extends AmqpAbstractResource<Connection> implements
     }
 
     public Connection getConnection() {
-        return new UnmodifiableConnection(getEndpoint());
+        return UnmodifiableProxy.connectionProxy(getEndpoint());
     }
 
     public AmqpConnectionListener getListener() {

http://git-wip-us.apache.org/repos/asf/activemq/blob/fddbac2b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/AmqpMessage.java
----------------------------------------------------------------------
diff --git a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/AmqpMessage.java b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/AmqpMessage.java
index da0c4e6..abb50da 100644
--- a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/AmqpMessage.java
+++ b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/AmqpMessage.java
@@ -20,7 +20,7 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.NoSuchElementException;
 
-import org.apache.activemq.transport.amqp.client.util.UnmodifiableDelivery;
+import org.apache.activemq.transport.amqp.client.util.UnmodifiableProxy;
 import org.apache.qpid.proton.Proton;
 import org.apache.qpid.proton.amqp.Binary;
 import org.apache.qpid.proton.amqp.DescribedType;
@@ -104,7 +104,7 @@ public class AmqpMessage {
      */
     public Delivery getWrappedDelivery() {
         if (delivery != null) {
-            return new UnmodifiableDelivery(delivery);
+            return UnmodifiableProxy.deliveryProxy(delivery);
         }
 
         return null;

http://git-wip-us.apache.org/repos/asf/activemq/blob/fddbac2b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/AmqpReceiver.java
----------------------------------------------------------------------
diff --git a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/AmqpReceiver.java b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/AmqpReceiver.java
index cfc355c..a3efa12 100644
--- a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/AmqpReceiver.java
+++ b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/AmqpReceiver.java
@@ -35,7 +35,7 @@ import javax.jms.InvalidDestinationException;
 import org.apache.activemq.transport.amqp.client.util.AsyncResult;
 import org.apache.activemq.transport.amqp.client.util.ClientFuture;
 import org.apache.activemq.transport.amqp.client.util.IOExceptionSupport;
-import org.apache.activemq.transport.amqp.client.util.UnmodifiableReceiver;
+import org.apache.activemq.transport.amqp.client.util.UnmodifiableProxy;
 import org.apache.qpid.jms.JmsOperationTimedOutException;
 import org.apache.qpid.proton.amqp.Binary;
 import org.apache.qpid.proton.amqp.DescribedType;
@@ -670,7 +670,7 @@ public class AmqpReceiver extends AmqpAbstractResource<Receiver> {
      * @return an unmodifiable view of the underlying Receiver instance.
      */
     public Receiver getReceiver() {
-        return new UnmodifiableReceiver(getEndpoint());
+        return UnmodifiableProxy.receiverProxy(getEndpoint());
     }
 
     //----- Receiver configuration properties --------------------------------//

http://git-wip-us.apache.org/repos/asf/activemq/blob/fddbac2b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/AmqpSender.java
----------------------------------------------------------------------
diff --git a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/AmqpSender.java b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/AmqpSender.java
index a48b856..db487bd 100644
--- a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/AmqpSender.java
+++ b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/AmqpSender.java
@@ -29,7 +29,7 @@ import javax.jms.InvalidDestinationException;
 
 import org.apache.activemq.transport.amqp.client.util.AsyncResult;
 import org.apache.activemq.transport.amqp.client.util.ClientFuture;
-import org.apache.activemq.transport.amqp.client.util.UnmodifiableSender;
+import org.apache.activemq.transport.amqp.client.util.UnmodifiableProxy;
 import org.apache.qpid.proton.amqp.Binary;
 import org.apache.qpid.proton.amqp.Symbol;
 import org.apache.qpid.proton.amqp.messaging.Accepted;
@@ -81,7 +81,6 @@ public class AmqpSender extends AmqpAbstractResource<Sender> {
     private Symbol[] offeredCapabilities;
     private Map<Symbol, Object> properties;
 
-
     /**
      * Create a new sender instance.
      *
@@ -230,7 +229,7 @@ public class AmqpSender extends AmqpAbstractResource<Sender> {
      * @return an unmodifiable view of the underlying Sender instance.
      */
     public Sender getSender() {
-        return new UnmodifiableSender(getEndpoint());
+        return UnmodifiableProxy.senderProxy(getEndpoint());
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/activemq/blob/fddbac2b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/AmqpSession.java
----------------------------------------------------------------------
diff --git a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/AmqpSession.java b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/AmqpSession.java
index 8956692..ebbe2b0 100644
--- a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/AmqpSession.java
+++ b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/AmqpSession.java
@@ -24,7 +24,7 @@ import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.activemq.transport.amqp.client.util.AsyncResult;
 import org.apache.activemq.transport.amqp.client.util.ClientFuture;
-import org.apache.activemq.transport.amqp.client.util.UnmodifiableSession;
+import org.apache.activemq.transport.amqp.client.util.UnmodifiableProxy;
 import org.apache.qpid.proton.amqp.Symbol;
 import org.apache.qpid.proton.amqp.messaging.Source;
 import org.apache.qpid.proton.amqp.messaging.Target;
@@ -597,7 +597,7 @@ public class AmqpSession extends AmqpAbstractResource<Session> {
     }
 
     public Session getSession() {
-        return new UnmodifiableSession(getEndpoint());
+        return UnmodifiableProxy.sessionProxy(getEndpoint());
     }
 
     public boolean isInTransaction() {

http://git-wip-us.apache.org/repos/asf/activemq/blob/fddbac2b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableConnection.java
----------------------------------------------------------------------
diff --git a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableConnection.java b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableConnection.java
deleted file mode 100644
index 032c0cd..0000000
--- a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableConnection.java
+++ /dev/null
@@ -1,202 +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.activemq.transport.amqp.client.util;
-
-import java.util.EnumSet;
-import java.util.Map;
-
-import org.apache.qpid.proton.amqp.Symbol;
-import org.apache.qpid.proton.amqp.transport.ErrorCondition;
-import org.apache.qpid.proton.engine.Collector;
-import org.apache.qpid.proton.engine.Connection;
-import org.apache.qpid.proton.engine.Delivery;
-import org.apache.qpid.proton.engine.EndpointState;
-import org.apache.qpid.proton.engine.Link;
-import org.apache.qpid.proton.engine.Record;
-import org.apache.qpid.proton.engine.Session;
-import org.apache.qpid.proton.engine.Transport;
-import org.apache.qpid.proton.reactor.Reactor;
-
-/**
- * Unmodifiable Connection wrapper used to prevent test code from accidentally
- * modifying Connection state.
- */
-public class UnmodifiableConnection implements Connection {
-
-    private final Connection connection;
-
-    public UnmodifiableConnection(Connection connection) {
-        this.connection = connection;
-    }
-
-    @Override
-    public EndpointState getLocalState() {
-        return connection.getLocalState();
-    }
-
-    @Override
-    public EndpointState getRemoteState() {
-        return connection.getRemoteState();
-    }
-
-    @Override
-    public ErrorCondition getCondition() {
-        return connection.getCondition();
-    }
-
-    @Override
-    public void setCondition(ErrorCondition condition) {
-        throw new UnsupportedOperationException("Cannot alter the Connection");
-    }
-
-    @Override
-    public ErrorCondition getRemoteCondition() {
-        return connection.getRemoteCondition();
-    }
-
-    @Override
-    public void free() {
-        throw new UnsupportedOperationException("Cannot alter the Connection");
-    }
-
-    @Override
-    public void open() {
-        throw new UnsupportedOperationException("Cannot alter the Connection");
-    }
-
-    @Override
-    public void close() {
-        throw new UnsupportedOperationException("Cannot alter the Connection");
-    }
-
-    @Override
-    public Session session() {
-        throw new UnsupportedOperationException("Cannot alter the Connection");
-    }
-
-    @Override
-    public Session sessionHead(EnumSet<EndpointState> local, EnumSet<EndpointState> remote) {
-        Session head = connection.sessionHead(local, remote);
-        if (head != null) {
-            head = new UnmodifiableSession(head);
-        }
-
-        return head;
-    }
-
-    @Override
-    public Link linkHead(EnumSet<EndpointState> local, EnumSet<EndpointState> remote) {
-        // TODO - If implemented this method should return an unmodifiable link isntance.
-        return null;
-    }
-
-    @Override
-    public Delivery getWorkHead() {
-        // TODO - If implemented this method should return an unmodifiable delivery isntance.
-        return null;
-    }
-
-    @Override
-    public void setContainer(String container) {
-        throw new UnsupportedOperationException("Cannot alter the Connection");
-    }
-
-    @Override
-    public void setHostname(String hostname) {
-        throw new UnsupportedOperationException("Cannot alter the Connection");
-    }
-
-    @Override
-    public String getHostname() {
-        return connection.getHostname();
-    }
-
-    @Override
-    public String getRemoteContainer() {
-        return connection.getRemoteContainer();
-    }
-
-    @Override
-    public String getRemoteHostname() {
-        return connection.getRemoteHostname();
-    }
-
-    @Override
-    public void setOfferedCapabilities(Symbol[] capabilities) {
-        throw new UnsupportedOperationException("Cannot alter the Connection");
-    }
-
-    @Override
-    public void setDesiredCapabilities(Symbol[] capabilities) {
-        throw new UnsupportedOperationException("Cannot alter the Connection");
-    }
-
-    @Override
-    public Symbol[] getRemoteOfferedCapabilities() {
-        return connection.getRemoteOfferedCapabilities();
-    }
-
-    @Override
-    public Symbol[] getRemoteDesiredCapabilities() {
-        return connection.getRemoteDesiredCapabilities();
-    }
-
-    @Override
-    public Map<Symbol, Object> getRemoteProperties() {
-        return connection.getRemoteProperties();
-    }
-
-    @Override
-    public void setProperties(Map<Symbol, Object> properties) {
-        throw new UnsupportedOperationException("Cannot alter the Connection");
-    }
-
-    @Override
-    public Object getContext() {
-        return connection.getContext();
-    }
-
-    @Override
-    public void setContext(Object context) {
-        throw new UnsupportedOperationException("Cannot alter the Connection");
-    }
-
-    @Override
-    public void collect(Collector collector) {
-        throw new UnsupportedOperationException("Cannot alter the Connection");
-    }
-
-    @Override
-    public String getContainer() {
-        return connection.getContainer();
-    }
-
-    @Override
-    public Transport getTransport() {
-        return new UnmodifiableTransport(connection.getTransport());
-    }
-
-    @Override
-    public Record attachments() {
-        return connection.attachments();
-    }
-
-    @Override
-    public Reactor getReactor() {
-        return connection.getReactor();
-    }
-}

http://git-wip-us.apache.org/repos/asf/activemq/blob/fddbac2b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableDelivery.java
----------------------------------------------------------------------
diff --git a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableDelivery.java b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableDelivery.java
deleted file mode 100644
index 438ae82..0000000
--- a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableDelivery.java
+++ /dev/null
@@ -1,173 +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.activemq.transport.amqp.client.util;
-
-import org.apache.qpid.proton.amqp.transport.DeliveryState;
-import org.apache.qpid.proton.engine.Delivery;
-import org.apache.qpid.proton.engine.Link;
-import org.apache.qpid.proton.engine.Receiver;
-import org.apache.qpid.proton.engine.Record;
-import org.apache.qpid.proton.engine.Sender;
-
-/**
- * Unmodifiable Delivery wrapper used to prevent test code from accidentally
- * modifying Delivery state.
- */
-public class UnmodifiableDelivery implements Delivery {
-
-    private final Delivery delivery;
-
-    public UnmodifiableDelivery(Delivery delivery) {
-        this.delivery = delivery;
-    }
-
-    @Override
-    public byte[] getTag() {
-        return delivery.getTag();
-    }
-
-    @Override
-    public Link getLink() {
-        if (delivery.getLink() instanceof Sender) {
-            return new UnmodifiableSender((Sender) delivery.getLink());
-        } else if (delivery.getLink() instanceof Receiver) {
-            return new UnmodifiableReceiver((Receiver) delivery.getLink());
-        } else {
-            throw new IllegalStateException("Delivery has unknown link type");
-        }
-    }
-
-    @Override
-    public DeliveryState getLocalState() {
-        return delivery.getLocalState();
-    }
-
-    @Override
-    public DeliveryState getRemoteState() {
-        return delivery.getRemoteState();
-    }
-
-    @Override
-    public int getMessageFormat() {
-        return delivery.getMessageFormat();
-    }
-
-    @Override
-    public void disposition(DeliveryState state) {
-        throw new UnsupportedOperationException("Cannot alter the Delivery state");
-    }
-
-    @Override
-    public void settle() {
-        throw new UnsupportedOperationException("Cannot alter the Delivery state");
-    }
-
-    @Override
-    public boolean isSettled() {
-        return delivery.isSettled();
-    }
-
-    @Override
-    public boolean remotelySettled() {
-        return delivery.remotelySettled();
-    }
-
-    @Override
-    public void free() {
-        throw new UnsupportedOperationException("Cannot alter the Delivery state");
-    }
-
-    @Override
-    public Delivery getWorkNext() {
-        return new UnmodifiableDelivery(delivery.getWorkNext());
-    }
-
-    @Override
-    public Delivery next() {
-        return new UnmodifiableDelivery(delivery.next());
-    }
-
-    @Override
-    public boolean isWritable() {
-        return delivery.isWritable();
-    }
-
-    @Override
-    public boolean isReadable() {
-        return delivery.isReadable();
-    }
-
-    @Override
-    public void setContext(Object o) {
-        throw new UnsupportedOperationException("Cannot alter the Delivery state");
-    }
-
-    @Override
-    public Object getContext() {
-        return delivery.getContext();
-    }
-
-    @Override
-    public boolean isUpdated() {
-        return delivery.isUpdated();
-    }
-
-    @Override
-    public void clear() {
-        throw new UnsupportedOperationException("Cannot alter the Delivery state");
-    }
-
-    @Override
-    public boolean isPartial() {
-        return delivery.isPartial();
-    }
-
-    @Override
-    public int pending() {
-        return delivery.pending();
-    }
-
-    @Override
-    public boolean isBuffered() {
-        return delivery.isBuffered();
-    }
-
-    @Override
-    public Record attachments() {
-        return delivery.attachments();
-    }
-
-    @Override
-    public DeliveryState getDefaultDeliveryState() {
-        return delivery.getDefaultDeliveryState();
-    }
-
-    @Override
-    public void setDefaultDeliveryState(DeliveryState state) {
-        throw new UnsupportedOperationException("Cannot alter the Delivery");
-    }
-
-    @Override
-    public void setMessageFormat(int messageFormat) {
-        throw new UnsupportedOperationException("Cannot alter the Delivery");
-    }
-
-    @Override
-    public int available() {
-        return delivery.available();
-    }
-}

http://git-wip-us.apache.org/repos/asf/activemq/blob/fddbac2b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableLink.java
----------------------------------------------------------------------
diff --git a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableLink.java b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableLink.java
deleted file mode 100644
index 76f240d..0000000
--- a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableLink.java
+++ /dev/null
@@ -1,322 +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.activemq.transport.amqp.client.util;
-
-import java.util.EnumSet;
-import java.util.Map;
-
-import org.apache.qpid.proton.amqp.Symbol;
-import org.apache.qpid.proton.amqp.UnsignedLong;
-import org.apache.qpid.proton.amqp.transport.ErrorCondition;
-import org.apache.qpid.proton.amqp.transport.ReceiverSettleMode;
-import org.apache.qpid.proton.amqp.transport.SenderSettleMode;
-import org.apache.qpid.proton.amqp.transport.Source;
-import org.apache.qpid.proton.amqp.transport.Target;
-import org.apache.qpid.proton.engine.Delivery;
-import org.apache.qpid.proton.engine.EndpointState;
-import org.apache.qpid.proton.engine.Link;
-import org.apache.qpid.proton.engine.Receiver;
-import org.apache.qpid.proton.engine.Record;
-import org.apache.qpid.proton.engine.Sender;
-import org.apache.qpid.proton.engine.Session;
-
-/**
- * Unmodifiable Session wrapper used to prevent test code from accidentally
- * modifying Session state.
- */
-public class UnmodifiableLink implements Link {
-
-    private final Link link;
-
-    public UnmodifiableLink(Link link) {
-        this.link = link;
-    }
-
-    @Override
-    public EndpointState getLocalState() {
-        return link.getLocalState();
-    }
-
-    @Override
-    public EndpointState getRemoteState() {
-        return link.getRemoteState();
-    }
-
-    @Override
-    public ErrorCondition getCondition() {
-        return link.getCondition();
-    }
-
-    @Override
-    public void setCondition(ErrorCondition condition) {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-
-    @Override
-    public ErrorCondition getRemoteCondition() {
-        return link.getRemoteCondition();
-    }
-
-    @Override
-    public void free() {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-
-    @Override
-    public void open() {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-
-    @Override
-    public void close() {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-
-    @Override
-    public void setContext(Object o) {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-
-    @Override
-    public Object getContext() {
-        return link.getContext();
-    }
-
-    @Override
-    public String getName() {
-        return link.getName();
-    }
-
-    @Override
-    public Delivery delivery(byte[] tag) {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-
-    @Override
-    public Delivery delivery(byte[] tag, int offset, int length) {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-
-    @Override
-    public Delivery head() {
-        return new UnmodifiableDelivery(link.head());
-    }
-
-    @Override
-    public Delivery current() {
-        return new UnmodifiableDelivery(link.current());
-    }
-
-    @Override
-    public boolean advance() {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-
-    @Override
-    public Source getSource() {
-        // TODO Figure out a simple way to wrap the odd Source types in Proton-J
-        return link.getSource();
-    }
-
-    @Override
-    public Target getTarget() {
-        // TODO Figure out a simple way to wrap the odd Source types in Proton-J
-        return link.getTarget();
-    }
-
-    @Override
-    public void setSource(Source address) {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-
-    @Override
-    public void setTarget(Target address) {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-
-    @Override
-    public Source getRemoteSource() {
-        // TODO Figure out a simple way to wrap the odd Source types in Proton-J
-        return link.getRemoteSource();
-    }
-
-    @Override
-    public Target getRemoteTarget() {
-        // TODO Figure out a simple way to wrap the odd Target types in Proton-J
-        return link.getRemoteTarget();
-    }
-
-    @Override
-    public Link next(EnumSet<EndpointState> local, EnumSet<EndpointState> remote) {
-        Link next = link.next(local, remote);
-
-        if (next != null) {
-            if (next instanceof Sender) {
-                next = new UnmodifiableSender((Sender) next);
-            } else {
-                next = new UnmodifiableReceiver((Receiver) next);
-            }
-        }
-
-        return next;
-    }
-
-    @Override
-    public int getCredit() {
-        return link.getCredit();
-    }
-
-    @Override
-    public int getQueued() {
-        return link.getQueued();
-    }
-
-    @Override
-    public int getUnsettled() {
-        return link.getUnsettled();
-    }
-
-    @Override
-    public Session getSession() {
-        return new UnmodifiableSession(link.getSession());
-    }
-
-    @Override
-    public SenderSettleMode getSenderSettleMode() {
-        return link.getSenderSettleMode();
-    }
-
-    @Override
-    public void setSenderSettleMode(SenderSettleMode senderSettleMode) {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-
-    @Override
-    public SenderSettleMode getRemoteSenderSettleMode() {
-        return link.getRemoteSenderSettleMode();
-    }
-
-    @Override
-    public ReceiverSettleMode getReceiverSettleMode() {
-        return link.getReceiverSettleMode();
-    }
-
-    @Override
-    public void setReceiverSettleMode(ReceiverSettleMode receiverSettleMode) {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-
-    @Override
-    public ReceiverSettleMode getRemoteReceiverSettleMode() {
-        return link.getRemoteReceiverSettleMode();
-    }
-
-    @Override
-    public void setRemoteSenderSettleMode(SenderSettleMode remoteSenderSettleMode) {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-
-    @Override
-    public int drained() {
-        return link.drained();  // TODO - Is this a mutating call?
-    }
-
-    @Override
-    public int getRemoteCredit() {
-        return link.getRemoteCredit();
-    }
-
-    @Override
-    public boolean getDrain() {
-        return link.getDrain();
-    }
-
-    @Override
-    public void detach() {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-
-    @Override
-    public boolean detached() {
-        return link.detached();
-    }
-
-    @Override
-    public Record attachments() {
-        return link.attachments();
-    }
-
-    @Override
-    public Map<Symbol, Object> getProperties() {
-        return link.getProperties();
-    }
-
-    @Override
-    public void setProperties(Map<Symbol, Object> properties) {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-
-    @Override
-    public Map<Symbol, Object> getRemoteProperties() {
-        return link.getRemoteProperties();
-    }
-
-    @Override
-    public Symbol[] getDesiredCapabilities() {
-        return link.getDesiredCapabilities();
-    }
-
-    @Override
-    public Symbol[] getOfferedCapabilities() {
-        return link.getOfferedCapabilities();
-    }
-
-    @Override
-    public Symbol[] getRemoteDesiredCapabilities() {
-        return link.getRemoteDesiredCapabilities();
-    }
-
-    @Override
-    public Symbol[] getRemoteOfferedCapabilities() {
-        return link.getRemoteOfferedCapabilities();
-    }
-
-    @Override
-    public void setDesiredCapabilities(Symbol[] capabilities) {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-
-    @Override
-    public void setOfferedCapabilities(Symbol[] capabilities) {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-
-    @Override
-    public UnsignedLong getMaxMessageSize() {
-        return link.getMaxMessageSize();
-    }
-
-    @Override
-    public UnsignedLong getRemoteMaxMessageSize() {
-        return link.getRemoteMaxMessageSize();
-    }
-
-    @Override
-    public void setMaxMessageSize(UnsignedLong maxMessageSize) {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-}

http://git-wip-us.apache.org/repos/asf/activemq/blob/fddbac2b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableProxy.java
----------------------------------------------------------------------
diff --git a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableProxy.java b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableProxy.java
new file mode 100644
index 0000000..e40e214
--- /dev/null
+++ b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableProxy.java
@@ -0,0 +1,167 @@
+/*
+ * 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.activemq.transport.amqp.client.util;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.qpid.proton.engine.Connection;
+import org.apache.qpid.proton.engine.Delivery;
+import org.apache.qpid.proton.engine.Link;
+import org.apache.qpid.proton.engine.Receiver;
+import org.apache.qpid.proton.engine.Sasl;
+import org.apache.qpid.proton.engine.Sender;
+import org.apache.qpid.proton.engine.Session;
+import org.apache.qpid.proton.engine.Transport;
+
+/**
+ * Utility that creates proxy objects for the Proton objects which
+ * won't allow any mutating operations to be applied so that the test
+ * code does not interact with the proton engine outside the client
+ * serialization thread.
+ */
+public final class UnmodifiableProxy {
+
+    private static ArrayList<String> blacklist = new ArrayList<>();
+
+    // These methods are mutating but don't take an arguments so they
+    // aren't automatically filtered out.  We will have to keep an eye
+    // on proton API in the future and modify this list as it evolves.
+    static {
+        blacklist.add("close");
+        blacklist.add("free");
+        blacklist.add("open");
+        blacklist.add("sasl");
+        blacklist.add("session");
+        blacklist.add("close_head");
+        blacklist.add("close_tail");
+        blacklist.add("outputConsumed");
+        blacklist.add("process");
+        blacklist.add("processInput");
+        blacklist.add("unbind");
+        blacklist.add("settle");
+        blacklist.add("clear");
+        blacklist.add("detach");
+        blacklist.add("abort");
+    }
+
+    private UnmodifiableProxy() {}
+
+    public static Transport transportProxy(final Transport target) {
+        Transport wrap = wrap(Transport.class, target);
+        return wrap;
+    }
+
+    public static Sasl saslProxy(final Sasl target) {
+        return wrap(Sasl.class, target);
+    }
+
+    public static Connection connectionProxy(final Connection target) {
+        return wrap(Connection.class, target);
+    }
+
+    public static Session sessionProxy(final Session target) {
+        return wrap(Session.class, target);
+    }
+
+    public static Delivery deliveryProxy(final Delivery target) {
+        return wrap(Delivery.class, target);
+    }
+
+    public static Link linkProxy(final Link target) {
+        return wrap(Link.class, target);
+    }
+
+    public static Receiver receiverProxy(final Receiver target) {
+       return wrap(Receiver.class, target);
+    }
+
+    public static Sender senderProxy(final Sender target) {
+        return wrap(Sender.class, target);
+    }
+
+    private static boolean isProtonType(Class<?> clazz) {
+        String packageName = clazz.getPackage().getName();
+
+        if (packageName.startsWith("org.apache.qpid.proton.")) {
+            return true;
+        }
+
+        return false;
+    }
+
+    private static <T> T wrap(Class<T> type, final Object target) {
+        return type.cast(java.lang.reflect.Proxy.newProxyInstance(type.getClassLoader(), new Class[]{type}, new InvocationHandler() {
+            @Override
+            public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
+                if ("toString".equals(method.getName()) && method.getParameterTypes().length == 0) {
+                    return "Unmodifiable proxy -> (" + method.invoke(target, objects) + ")";
+                }
+
+                // Don't let methods that mutate be invoked.
+                if (method.getParameterTypes().length > 0) {
+                    throw new UnsupportedOperationException("Cannot mutate outside the Client work thread");
+                }
+
+                if (blacklist.contains(method.getName())) {
+                    throw new UnsupportedOperationException("Cannot mutate outside the Client work thread");
+                }
+
+                Class<?> returnType = method.getReturnType();
+
+                try {
+                    Object result = method.invoke(target, objects);
+                    if (result == null) {
+                        return null;
+                    }
+
+                    if (returnType.isPrimitive() || returnType.isArray() || Object.class.equals(returnType)) {
+                        // Skip any other checks
+                    } else if (returnType.isAssignableFrom(ByteBuffer.class)) {
+                        // Buffers are modifiable but we can just return null to indicate
+                        // there's nothing there to access.
+                        result = null;
+                    } else if (returnType.isAssignableFrom(Map.class)) {
+                        // Prevent return of modifiable maps
+                        result = Collections.unmodifiableMap((Map<?, ?>) result);
+                    } else if (isProtonType(returnType) && returnType.isInterface()) {
+
+                        // Can't handle the crazy Source / Target types yet as there's two
+                        // different types for Source and Target the result can't be cast to
+                        // the one people actually want to use.
+                        if (!returnType.getName().equals("org.apache.qpid.proton.amqp.transport.Source") &&
+                            !returnType.getName().equals("org.apache.qpid.proton.amqp.messaging.Source") &&
+                            !returnType.getName().equals("org.apache.qpid.proton.amqp.transport.Target") &&
+                            !returnType.getName().equals("org.apache.qpid.proton.amqp.messaging.Target")) {
+
+                            result = wrap(returnType, result);
+                        }
+                    }
+
+                    return result;
+                } catch (InvocationTargetException e) {
+                    throw e.getTargetException();
+                }
+            }
+        }));
+    }
+}

http://git-wip-us.apache.org/repos/asf/activemq/blob/fddbac2b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableReceiver.java
----------------------------------------------------------------------
diff --git a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableReceiver.java b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableReceiver.java
deleted file mode 100644
index 121a7f5..0000000
--- a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableReceiver.java
+++ /dev/null
@@ -1,65 +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.activemq.transport.amqp.client.util;
-
-import org.apache.qpid.proton.codec.WritableBuffer;
-import org.apache.qpid.proton.engine.Receiver;
-
-/**
- * Unmodifiable Receiver wrapper used to prevent test code from accidentally
- * modifying Receiver state.
- */
-public class UnmodifiableReceiver extends UnmodifiableLink implements Receiver {
-
-    private final Receiver receiver;
-
-    public UnmodifiableReceiver(Receiver receiver) {
-        super(receiver);
-
-        this.receiver = receiver;
-    }
-
-    @Override
-    public void flow(int credits) {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-
-    @Override
-    public int recv(byte[] bytes, int offset, int size) {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-
-    @Override
-    public void drain(int credit) {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-
-    @Override
-    public boolean draining() {
-        return receiver.draining();
-    }
-
-    @Override
-    public void setDrain(boolean drain) {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-
-    @Override
-    public int recv(WritableBuffer buffer) {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-}

http://git-wip-us.apache.org/repos/asf/activemq/blob/fddbac2b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableSender.java
----------------------------------------------------------------------
diff --git a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableSender.java b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableSender.java
deleted file mode 100644
index fbe5772..0000000
--- a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableSender.java
+++ /dev/null
@@ -1,51 +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.activemq.transport.amqp.client.util;
-
-import org.apache.qpid.proton.codec.ReadableBuffer;
-import org.apache.qpid.proton.engine.Sender;
-
-/**
- * Unmodifiable Sender wrapper used to prevent test code from accidentally
- * modifying Sender state.
- */
-public class UnmodifiableSender extends UnmodifiableLink implements Sender {
-
-    public UnmodifiableSender(Sender sender) {
-        super(sender);
-    }
-
-    @Override
-    public void offer(int credits) {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-
-    @Override
-    public int send(byte[] bytes, int offset, int length) {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-
-    @Override
-    public void abort() {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-
-    @Override
-    public int send(ReadableBuffer buffer) {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-}

http://git-wip-us.apache.org/repos/asf/activemq/blob/fddbac2b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableSession.java
----------------------------------------------------------------------
diff --git a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableSession.java b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableSession.java
deleted file mode 100644
index 055bb51..0000000
--- a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableSession.java
+++ /dev/null
@@ -1,197 +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.activemq.transport.amqp.client.util;
-
-import java.util.EnumSet;
-import java.util.Map;
-
-import org.apache.qpid.proton.amqp.Symbol;
-import org.apache.qpid.proton.amqp.transport.ErrorCondition;
-import org.apache.qpid.proton.engine.Connection;
-import org.apache.qpid.proton.engine.EndpointState;
-import org.apache.qpid.proton.engine.Receiver;
-import org.apache.qpid.proton.engine.Record;
-import org.apache.qpid.proton.engine.Sender;
-import org.apache.qpid.proton.engine.Session;
-
-/**
- * Unmodifiable Session wrapper used to prevent test code from accidentally
- * modifying Session state.
- */
-public class UnmodifiableSession implements Session {
-
-    private final Session session;
-
-    public UnmodifiableSession(Session session) {
-        this.session = session;
-    }
-
-    @Override
-    public EndpointState getLocalState() {
-        return session.getLocalState();
-    }
-
-    @Override
-    public EndpointState getRemoteState() {
-        return session.getRemoteState();
-    }
-
-    @Override
-    public ErrorCondition getCondition() {
-        return session.getCondition();
-    }
-
-    @Override
-    public void setCondition(ErrorCondition condition) {
-        throw new UnsupportedOperationException("Cannot alter the Session");
-    }
-
-    @Override
-    public ErrorCondition getRemoteCondition() {
-        return session.getRemoteCondition();
-    }
-
-    @Override
-    public void free() {
-        throw new UnsupportedOperationException("Cannot alter the Session");
-    }
-
-    @Override
-    public void open() {
-        throw new UnsupportedOperationException("Cannot alter the Session");
-    }
-
-    @Override
-    public void close() {
-        throw new UnsupportedOperationException("Cannot alter the Session");
-    }
-
-    @Override
-    public void setContext(Object o) {
-        throw new UnsupportedOperationException("Cannot alter the Session");
-    }
-
-    @Override
-    public Object getContext() {
-        return session.getContext();
-    }
-
-    @Override
-    public Sender sender(String name) {
-        throw new UnsupportedOperationException("Cannot alter the Session");
-    }
-
-    @Override
-    public Receiver receiver(String name) {
-        throw new UnsupportedOperationException("Cannot alter the Session");
-    }
-
-    @Override
-    public Session next(EnumSet<EndpointState> local, EnumSet<EndpointState> remote) {
-        Session next = session.next(local, remote);
-        if (next != null) {
-            next = new UnmodifiableSession(next);
-        }
-
-        return next;
-    }
-
-    @Override
-    public Connection getConnection() {
-        return new UnmodifiableConnection(session.getConnection());
-    }
-
-    @Override
-    public int getIncomingCapacity() {
-        return session.getIncomingCapacity();
-    }
-
-    @Override
-    public void setIncomingCapacity(int bytes) {
-        throw new UnsupportedOperationException("Cannot alter the Session");
-    }
-
-    @Override
-    public int getIncomingBytes() {
-        return session.getIncomingBytes();
-    }
-
-    @Override
-    public int getOutgoingBytes() {
-        return session.getOutgoingBytes();
-    }
-
-    @Override
-    public Record attachments() {
-        return session.attachments();
-    }
-
-    @Override
-    public long getOutgoingWindow() {
-        return session.getOutgoingWindow();
-    }
-
-    @Override
-    public void setOutgoingWindow(long outgoingWindowSize) {
-        throw new UnsupportedOperationException("Cannot alter the Session");
-    }
-
-    @Override
-    public Symbol[] getDesiredCapabilities() {
-        return session.getDesiredCapabilities();
-    }
-
-    @Override
-    public Symbol[] getOfferedCapabilities() {
-        return session.getOfferedCapabilities();
-    }
-
-    @Override
-    public Map<Symbol, Object> getProperties() {
-        return session.getProperties();
-    }
-
-    @Override
-    public Symbol[] getRemoteDesiredCapabilities() {
-        return session.getRemoteDesiredCapabilities();
-    }
-
-    @Override
-    public Symbol[] getRemoteOfferedCapabilities() {
-        return session.getRemoteOfferedCapabilities();
-    }
-
-    @Override
-    public Map<Symbol, Object> getRemoteProperties() {
-        return session.getRemoteProperties();
-    }
-
-    @Override
-    public void setDesiredCapabilities(Symbol[] capabilities) {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-
-    @Override
-    public void setOfferedCapabilities(Symbol[] capabilities) {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-
-    @Override
-    public void setProperties(Map<Symbol, Object> capabilities) {
-        throw new UnsupportedOperationException("Cannot alter the Link state");
-    }
-}

http://git-wip-us.apache.org/repos/asf/activemq/blob/fddbac2b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableTransport.java
----------------------------------------------------------------------
diff --git a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableTransport.java b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableTransport.java
deleted file mode 100644
index 0f2a5bc..0000000
--- a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/client/util/UnmodifiableTransport.java
+++ /dev/null
@@ -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.activemq.transport.amqp.client.util;
-
-import java.nio.ByteBuffer;
-
-import org.apache.qpid.proton.amqp.transport.ErrorCondition;
-import org.apache.qpid.proton.engine.Connection;
-import org.apache.qpid.proton.engine.EndpointState;
-import org.apache.qpid.proton.engine.Record;
-import org.apache.qpid.proton.engine.Sasl;
-import org.apache.qpid.proton.engine.Ssl;
-import org.apache.qpid.proton.engine.SslDomain;
-import org.apache.qpid.proton.engine.SslPeerDetails;
-import org.apache.qpid.proton.engine.Transport;
-import org.apache.qpid.proton.engine.TransportException;
-import org.apache.qpid.proton.engine.TransportResult;
-
-/**
- * Unmodifiable Transport wrapper used to prevent test code from accidentally
- * modifying Transport state.
- */
-public class UnmodifiableTransport implements Transport {
-
-    private final Transport transport;
-
-    public UnmodifiableTransport(Transport transport) {
-        this.transport = transport;
-    }
-
-    @Override
-    public void close() {
-        throw new UnsupportedOperationException("Cannot alter the Transport");
-    }
-
-    @Override
-    public void free() {
-        throw new UnsupportedOperationException("Cannot alter the Transport");
-    }
-
-    @Override
-    public Object getContext() {
-        return null;
-    }
-
-    @Override
-    public EndpointState getLocalState() {
-        return transport.getLocalState();
-    }
-
-    @Override
-    public ErrorCondition getRemoteCondition() {
-        return transport.getRemoteCondition();
-    }
-
-    @Override
-    public EndpointState getRemoteState() {
-        return transport.getRemoteState();
-    }
-
-    @Override
-    public void open() {
-        throw new UnsupportedOperationException("Cannot alter the Transport");
-    }
-
-    @Override
-    public void setCondition(ErrorCondition arg0) {
-        throw new UnsupportedOperationException("Cannot alter the Transport");
-    }
-
-    @Override
-    public void setContext(Object arg0) {
-        throw new UnsupportedOperationException("Cannot alter the Transport");
-    }
-
-    @Override
-    public void bind(Connection arg0) {
-        throw new UnsupportedOperationException("Cannot alter the Transport");
-    }
-
-    @Override
-    public int capacity() {
-        return transport.capacity();
-    }
-
-    @Override
-    public void close_head() {
-        throw new UnsupportedOperationException("Cannot alter the Transport");
-    }
-
-    @Override
-    public void close_tail() {
-        throw new UnsupportedOperationException("Cannot alter the Transport");
-    }
-
-    @Override
-    public int getChannelMax() {
-        return transport.getChannelMax();
-    }
-
-    @Override
-    public ErrorCondition getCondition() {
-        return transport.getCondition();
-    }
-
-    @Override
-    public int getIdleTimeout() {
-        return transport.getIdleTimeout();
-    }
-
-    @Override
-    public ByteBuffer getInputBuffer() {
-        return null;
-    }
-
-    @Override
-    public int getMaxFrameSize() {
-        return transport.getMaxFrameSize();
-    }
-
-    @Override
-    public ByteBuffer getOutputBuffer() {
-        return null;
-    }
-
-    @Override
-    public int getRemoteChannelMax() {
-        return transport.getRemoteChannelMax();
-    }
-
-    @Override
-    public int getRemoteIdleTimeout() {
-        return transport.getRemoteIdleTimeout();
-    }
-
-    @Override
-    public int getRemoteMaxFrameSize() {
-        return transport.getRemoteMaxFrameSize();
-    }
-
-    @Override
-    public ByteBuffer head() {
-        return null;
-    }
-
-    @Override
-    public int input(byte[] arg0, int arg1, int arg2) {
-        throw new UnsupportedOperationException("Cannot alter the Transport");
-    }
-
-    @Override
-    public boolean isClosed() {
-        return transport.isClosed();
-    }
-
-    @Override
-    public int output(byte[] arg0, int arg1, int arg2) {
-        throw new UnsupportedOperationException("Cannot alter the Transport");
-    }
-
-    @Override
-    public void outputConsumed() {
-        throw new UnsupportedOperationException("Cannot alter the Transport");
-    }
-
-    @Override
-    public int pending() {
-        return transport.pending();
-    }
-
-    @Override
-    public void pop(int arg0) {
-        throw new UnsupportedOperationException("Cannot alter the Transport");
-    }
-
-    @Override
-    public void process() throws TransportException {
-        throw new UnsupportedOperationException("Cannot alter the Transport");
-    }
-
-    @Override
-    public TransportResult processInput() {
-        throw new UnsupportedOperationException("Cannot alter the Transport");
-    }
-
-    @Override
-    public Sasl sasl() throws IllegalStateException {
-        throw new UnsupportedOperationException("Cannot alter the Transport");
-    }
-
-    @Override
-    public void setChannelMax(int arg0) {
-        throw new UnsupportedOperationException("Cannot alter the Transport");
-    }
-
-    @Override
-    public void setIdleTimeout(int arg0) {
-        throw new UnsupportedOperationException("Cannot alter the Transport");
-    }
-
-    @Override
-    public void setMaxFrameSize(int arg0) {
-        throw new UnsupportedOperationException("Cannot alter the Transport");
-    }
-
-    @Override
-    public Ssl ssl(SslDomain arg0) {
-        throw new UnsupportedOperationException("Cannot alter the Transport");
-    }
-
-    @Override
-    public Ssl ssl(SslDomain arg0, SslPeerDetails arg1) {
-        throw new UnsupportedOperationException("Cannot alter the Transport");
-    }
-
-    @Override
-    public ByteBuffer tail() {
-        return null;
-    }
-
-    @Override
-    public long tick(long arg0) {
-        throw new UnsupportedOperationException("Cannot alter the Transport");
-    }
-
-    @Override
-    public void trace(int arg0) {
-        throw new UnsupportedOperationException("Cannot alter the Transport");
-    }
-
-    @Override
-    public void unbind() {
-        throw new UnsupportedOperationException("Cannot alter the Transport");
-    }
-
-    @Override
-    public Record attachments() {
-        return transport.attachments();
-    }
-
-    @Override
-    public long getFramesInput() {
-        return transport.getFramesInput();
-    }
-
-    @Override
-    public long getFramesOutput() {
-        return transport.getFramesOutput();
-    }
-
-    @Override
-    public void setEmitFlowEventOnSend(boolean emitFlowEventOnSend) {
-        throw new UnsupportedOperationException("Cannot alter the Transport");
-    }
-
-    @Override
-    public boolean isEmitFlowEventOnSend() {
-        return transport.isEmitFlowEventOnSend();
-    }
-}

http://git-wip-us.apache.org/repos/asf/activemq/blob/fddbac2b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/interop/AmqpConnectionsTest.java
----------------------------------------------------------------------
diff --git a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/interop/AmqpConnectionsTest.java b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/interop/AmqpConnectionsTest.java
index a3474a9..6d9847d 100644
--- a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/interop/AmqpConnectionsTest.java
+++ b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/interop/AmqpConnectionsTest.java
@@ -23,6 +23,7 @@ import static org.apache.activemq.transport.amqp.AmqpSupport.VERSION;
 import static org.apache.activemq.transport.amqp.AmqpSupport.contains;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.fail;
 
 import java.util.Arrays;
@@ -83,6 +84,32 @@ public class AmqpConnectionsTest extends AmqpClientTestSupport {
 
         assertEquals(1, getProxyToBroker().getCurrentConnectionsCount());
 
+
+        Connection protonConnection = connection.getConnection();
+        org.apache.qpid.proton.engine.Transport protonTransport = protonConnection.getTransport();
+
+        protonTransport.getChannelMax();
+
+        assertNull(protonTransport.head());
+        assertNull(protonTransport.tail());
+        assertNull(protonTransport.getInputBuffer());
+        assertNull(protonTransport.getOutputBuffer());
+
+        try {
+            protonTransport.bind(protonConnection);
+            fail("Should not be able to mutate");
+        } catch (UnsupportedOperationException e) {}
+
+        try {
+            protonTransport.close();
+            fail("Should not be able to mutate");
+        } catch (UnsupportedOperationException e) {}
+
+        try {
+            protonTransport.setChannelMax(1);
+            fail("Should not be able to mutate");
+        } catch (UnsupportedOperationException e) {}
+
         connection.close();
 
         assertEquals(0, getProxyToBroker().getCurrentConnectionsCount());

http://git-wip-us.apache.org/repos/asf/activemq/blob/fddbac2b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/interop/AmqpSessionTest.java
----------------------------------------------------------------------
diff --git a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/interop/AmqpSessionTest.java b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/interop/AmqpSessionTest.java
index cf647e0..2957849 100644
--- a/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/interop/AmqpSessionTest.java
+++ b/activemq-amqp/src/test/java/org/apache/activemq/transport/amqp/interop/AmqpSessionTest.java
@@ -17,6 +17,8 @@
 package org.apache.activemq.transport.amqp.interop;
 
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
 
 import org.apache.activemq.transport.amqp.client.AmqpClient;
 import org.apache.activemq.transport.amqp.client.AmqpClientTestSupport;
@@ -43,6 +45,39 @@ public class AmqpSessionTest extends AmqpClientTestSupport {
         AmqpConnection connection = trackConnection(client.connect());
         AmqpSession session = connection.createSession();
         assertNotNull(session);
+
+        Session protonSession = session.getSession();
+
+        try {
+            protonSession.close();
+            fail("Should not be able to mutate.");
+        } catch (UnsupportedOperationException ex) {}
+
+        try {
+            protonSession.free();
+            fail("Should not be able to mutate.");
+        } catch (UnsupportedOperationException ex) {}
+
+        try {
+            protonSession.getConnection().close();
+            fail("Should not be able to mutate.");
+        } catch (UnsupportedOperationException ex) {}
+
+        try {
+            protonSession.open();
+            fail("Should not be able to mutate.");
+        } catch (UnsupportedOperationException ex) {}
+
+        assertNull(protonSession.getProperties());
+        assertNull(protonSession.getOfferedCapabilities());
+
+        assertNotNull(protonSession.getContext());
+
+        try {
+            protonSession.receiver("sender");
+            fail("Should not be able to mutate.");
+        } catch (UnsupportedOperationException ex) {}
+
         connection.close();
     }