PROTON-1409: expose the current available byte count for a delivery to aid with sizing destination buffers

This closes #7
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/Delivery.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/Delivery.java
index c5f6d73..58c62b6 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/engine/Delivery.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/Delivery.java
@@ -143,4 +143,20 @@
      */
     public int getMessageFormat();
 
+    /**
+     * Returns the number of bytes currently available for this delivery, which may not be complete yet, that are still
+     * to either be received by the application or sent by the transport.
+     *
+     * Note that this value will change as bytes are received/sent, and is in general not equal to the total length of
+     * a delivery, except the point where {@link #isPartial()} returns false and no content has yet been received by the
+     * application or sent by the transport.
+     *
+     * @return the number of bytes currently available for the delivery
+     *
+     * @see Receiver#recv(byte[], int, int)
+     * @see Receiver#recv(org.apache.qpid.proton.codec.WritableBuffer)
+     * @see Sender#send(byte[], int, int)
+     * @see Sender#send(org.apache.qpid.proton.codec.ReadableBuffer)
+     */
+    int available();
 }
diff --git a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/DeliveryImpl.java b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/DeliveryImpl.java
index 8b47231..61f8ec8 100644
--- a/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/DeliveryImpl.java
+++ b/proton-j/src/main/java/org/apache/qpid/proton/engine/impl/DeliveryImpl.java
@@ -387,6 +387,12 @@
     }
 
     @Override
+    public int available()
+    {
+        return _dataSize;
+    }
+
+    @Override
     public boolean isWritable()
     {
         return getLink() instanceof SenderImpl
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/DeferredSettlementTest.java b/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/DeferredSettlementTest.java
index 34a26e6..10ff811 100644
--- a/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/DeferredSettlementTest.java
+++ b/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/DeferredSettlementTest.java
@@ -413,10 +413,13 @@
         assertFalse(delivery.isPartial());
         assertTrue(delivery.isReadable());
 
-        byte[] received = new byte[BUFFER_SIZE];
-        int len = clientReceiver.recv(received, 0, BUFFER_SIZE);
+        int size = delivery.available();
+        byte[] received = new byte[size];
 
-        assertTrue("given array was too small", len < BUFFER_SIZE);
+        int len = clientReceiver.recv(received, 0, size);
+
+        assertEquals("Should have received " + size + " bytes", size, len);
+        assertEquals("Should be no bytes left", 0, delivery.available());
 
         Message m = Proton.message();
         m.decode(received, 0, len);
diff --git a/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/DeliveryImplTest.java b/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/DeliveryImplTest.java
index a063265..b754d5c 100644
--- a/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/DeliveryImplTest.java
+++ b/proton-j/src/test/java/org/apache/qpid/proton/engine/impl/DeliveryImplTest.java
@@ -22,7 +22,11 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
 
+import java.nio.charset.StandardCharsets;
+
+import org.apache.qpid.proton.engine.Delivery;
 import org.apache.qpid.proton.engine.Record;
 import org.junit.Test;
 import org.mockito.Mockito;
@@ -74,4 +78,39 @@
         Record attachments2 = delivery.attachments();
         assertSame("Expected to get the same attachments", attachments, attachments2);
     }
+
+    @Test
+    public void testAvailable() throws Exception
+    {
+        // Set up a delivery with some data
+        byte[] myData = "myData".getBytes(StandardCharsets.UTF_8);
+
+        DeliveryImpl deliveyImpl = new DeliveryImpl(null, Mockito.mock(LinkImpl.class), null);
+        deliveyImpl.setData(myData);
+        deliveyImpl.setDataLength(myData.length);
+
+        Delivery delivery = deliveyImpl;
+
+        // Check the full data is available
+        assertNotNull("expected the delivery to be present", delivery);
+        assertEquals("unexpectd available count", myData.length, delivery.available());
+
+        // Extract some of the data as the receiver link will, check available gets reduced accordingly.
+        int partLength = 2;
+        int remainderLength = myData.length - partLength;
+        assertTrue(partLength < myData.length);
+
+        byte[] myRecievedData1 = new byte[partLength];
+
+        int received = deliveyImpl.recv(myRecievedData1, 0, myRecievedData1.length);
+        assertEquals("Unexpected data length received", partLength, received);
+        assertEquals("Unexpected data length available", remainderLength, delivery.available());
+
+        // Extract remainder of the data as the receiver link will, check available hits 0.
+        byte[] myRecievedData2 = new byte[remainderLength];
+
+        received = deliveyImpl.recv(myRecievedData2, 0, remainderLength);
+        assertEquals("Unexpected data length received", remainderLength, received);
+        assertEquals("Expected no data to remain available", 0, delivery.available());
+    }
 }