You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ro...@apache.org on 2011/06/07 17:04:43 UTC

svn commit: r1133037 - in /qpid/trunk/qpid/java: client/src/main/java/org/apache/qpid/client/ common/src/main/java/org/apache/qpid/ common/src/main/java/org/apache/qpid/framing/ common/src/test/java/org/apache/qpid/ common/src/test/java/org/apache/qpid...

Author: robbie
Date: Tue Jun  7 15:04:42 2011
New Revision: 1133037

URL: http://svn.apache.org/viewvc?rev=1133037&view=rev
Log:
QPID-2158: add length validation into AMQShortString, remove dead code from AMQDestinations, truncate exception messages with length over 255 before sending them over the wire in AMQChannelException and AMQConnectionException.

Applied patch by Oleksandr Rudyy <or...@gmail.com>

Modified:
    qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java
    qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/AMQChannelException.java
    qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/AMQConnectionException.java
    qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/AMQException.java
    qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java
    qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/AMQExceptionTest.java
    qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/framing/AMQShortStringTest.java

Modified: qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java?rev=1133037&r1=1133036&r2=1133037&view=diff
==============================================================================
--- qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java (original)
+++ qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java Tue Jun  7 15:04:42 2011
@@ -21,8 +21,6 @@
 package org.apache.qpid.client;
 
 import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.List;
 import java.util.Map;
 
 import javax.jms.Destination;
@@ -34,8 +32,6 @@ import javax.naming.StringRefAddr;
 import org.apache.qpid.client.messaging.address.AddressHelper;
 import org.apache.qpid.client.messaging.address.Link;
 import org.apache.qpid.client.messaging.address.Node;
-import org.apache.qpid.client.messaging.address.QpidExchangeOptions;
-import org.apache.qpid.client.messaging.address.QpidQueueOptions;
 import org.apache.qpid.configuration.ClientProperties;
 import org.apache.qpid.exchange.ExchangeDefaults;
 import org.apache.qpid.framing.AMQShortString;
@@ -78,11 +74,6 @@ public abstract class AMQDestination imp
 
     private boolean _exchangeExistsChecked;
 
-    private byte[] _byteEncoding;
-    private static final int IS_DURABLE_MASK = 0x1;
-    private static final int IS_EXCLUSIVE_MASK = 0x2;
-    private static final int IS_AUTODELETE_MASK = 0x4;
-
     public static final int QUEUE_TYPE = 1;
     public static final int TOPIC_TYPE = 2;
     public static final int UNKNOWN_TYPE = 3;
@@ -323,7 +314,11 @@ public abstract class AMQDestination imp
     {
         if(_urlAsShortString == null)
         {
-            toURL();
+            if (_url == null)
+            {
+                toURL();
+            }
+            _urlAsShortString = new AMQShortString(_url);
         }
         return _urlAsShortString;
     }
@@ -370,7 +365,6 @@ public abstract class AMQDestination imp
         // calculated URL now out of date
         _url = null;
         _urlAsShortString = null;
-        _byteEncoding = null;
     }
 
     public AMQShortString getRoutingKey()
@@ -508,59 +502,10 @@ public abstract class AMQDestination imp
             sb.deleteCharAt(sb.length() - 1);
             url = sb.toString();
             _url = url;
-            _urlAsShortString = new AMQShortString(url);
         }
         return url;
     }
 
-    public byte[] toByteEncoding()
-    {
-        byte[] encoding = _byteEncoding;
-        if(encoding == null)
-        {
-            int size = _exchangeClass.length() + 1 +
-                       _exchangeName.length() + 1 +
-                       0 +  // in place of the destination name
-                       (_queueName == null ? 0 : _queueName.length()) + 1 +
-                       1;
-            encoding = new byte[size];
-            int pos = 0;
-
-            pos = _exchangeClass.writeToByteArray(encoding, pos);
-            pos = _exchangeName.writeToByteArray(encoding, pos);
-
-            encoding[pos++] = (byte)0;
-
-            if(_queueName == null)
-            {
-                encoding[pos++] = (byte)0;
-            }
-            else
-            {
-                pos = _queueName.writeToByteArray(encoding,pos);
-            }
-            byte options = 0;
-            if(_isDurable)
-            {
-                options |= IS_DURABLE_MASK;
-            }
-            if(_isExclusive)
-            {
-                options |= IS_EXCLUSIVE_MASK;
-            }
-            if(_isAutoDelete)
-            {
-                options |= IS_AUTODELETE_MASK;
-            }
-            encoding[pos] = options;
-
-
-            _byteEncoding = encoding;
-
-        }
-        return encoding;
-    }
-
     public boolean equals(Object o)
     {
         if (this == o)
@@ -614,53 +559,6 @@ public abstract class AMQDestination imp
                 null);          // factory location
     }
 
-
-    public static Destination createDestination(byte[] byteEncodedDestination)
-    {
-        AMQShortString exchangeClass;
-        AMQShortString exchangeName;
-        AMQShortString routingKey;
-        AMQShortString queueName;
-        boolean isDurable;
-        boolean isExclusive;
-        boolean isAutoDelete;
-
-        int pos = 0;
-        exchangeClass = AMQShortString.readFromByteArray(byteEncodedDestination, pos);
-        pos+= exchangeClass.length() + 1;
-        exchangeName =  AMQShortString.readFromByteArray(byteEncodedDestination, pos);
-        pos+= exchangeName.length() + 1;
-        routingKey =  AMQShortString.readFromByteArray(byteEncodedDestination, pos);
-        pos+= (routingKey == null ? 0 : routingKey.length()) + 1;
-        queueName =  AMQShortString.readFromByteArray(byteEncodedDestination, pos);
-        pos+= (queueName == null ? 0 : queueName.length()) + 1;
-        int options = byteEncodedDestination[pos];
-        isDurable = (options & IS_DURABLE_MASK) != 0;
-        isExclusive = (options & IS_EXCLUSIVE_MASK) != 0;
-        isAutoDelete = (options & IS_AUTODELETE_MASK) != 0;
-
-        if (exchangeClass.equals(ExchangeDefaults.DIRECT_EXCHANGE_CLASS))
-        {
-            return new AMQQueue(exchangeName,routingKey,queueName,isExclusive,isAutoDelete,isDurable);
-        }
-        else if (exchangeClass.equals(ExchangeDefaults.TOPIC_EXCHANGE_CLASS))
-        {
-            return new AMQTopic(exchangeName,routingKey,isAutoDelete,queueName,isDurable);
-        }
-        else if (exchangeClass.equals(ExchangeDefaults.HEADERS_EXCHANGE_CLASS))
-        {
-            return new AMQHeadersExchange(routingKey);
-        }
-        else
-        {
-            return new AMQAnyDestination(exchangeName,exchangeClass,
-                                         routingKey,isExclusive, 
-                                         isAutoDelete,queueName, 
-                                         isDurable, new AMQShortString[0]);
-        }
-
-    }
-
     public static Destination createDestination(BindingURL binding)
     {
         AMQShortString type = binding.getExchangeClass();

Modified: qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/AMQChannelException.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/AMQChannelException.java?rev=1133037&r1=1133036&r2=1133037&view=diff
==============================================================================
--- qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/AMQChannelException.java (original)
+++ qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/AMQChannelException.java Tue Jun  7 15:04:42 2011
@@ -54,6 +54,7 @@ public class AMQChannelException extends
     public AMQFrame getCloseFrame(int channel)
     {
         MethodRegistry reg = MethodRegistry.getMethodRegistry(new ProtocolVersion(major,minor));
-        return new AMQFrame(channel, reg.createChannelCloseBody(getErrorCode() == null ? AMQConstant.INTERNAL_ERROR.getCode() : getErrorCode().getCode(), new AMQShortString(getMessage()),_classId,_methodId));
+        return new AMQFrame(channel, reg.createChannelCloseBody(getErrorCode() == null ? AMQConstant.INTERNAL_ERROR.getCode() : getErrorCode().getCode(), getMessageAsShortString(),_classId,_methodId));
     }
+
 }

Modified: qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/AMQConnectionException.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/AMQConnectionException.java?rev=1133037&r1=1133036&r2=1133037&view=diff
==============================================================================
--- qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/AMQConnectionException.java (original)
+++ qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/AMQConnectionException.java Tue Jun  7 15:04:42 2011
@@ -62,9 +62,10 @@ public class AMQConnectionException exte
         MethodRegistry reg = MethodRegistry.getMethodRegistry(new ProtocolVersion(major,minor));
         return new AMQFrame(0,
                             reg.createConnectionCloseBody(getErrorCode().getCode(),
-                                                          new AMQShortString(getMessage()),
+                                                          getMessageAsShortString(),
                                                           _classId,
                                                           _methodId));
 
     }
+
 }

Modified: qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/AMQException.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/AMQException.java?rev=1133037&r1=1133036&r2=1133037&view=diff
==============================================================================
--- qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/AMQException.java (original)
+++ qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/AMQException.java Tue Jun  7 15:04:42 2011
@@ -20,6 +20,7 @@
  */
 package org.apache.qpid;
 
+import org.apache.qpid.framing.AMQShortString;
 import org.apache.qpid.protocol.AMQConstant;
 
 /**
@@ -121,4 +122,19 @@ public class AMQException extends Except
 
         return newAMQE;
     }
+
+    /**
+     * Truncates the exception message to 255 characters if its length exceeds 255.
+     *
+     * @return exception message
+     */
+    public AMQShortString getMessageAsShortString()
+    {
+        String message = getMessage();
+        if (message != null && message.length() > AMQShortString.MAX_LENGTH)
+        {
+            message = message.substring(0, AMQShortString.MAX_LENGTH - 3) + "...";
+        }
+        return new AMQShortString(message);
+    }
 }

Modified: qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java?rev=1133037&r1=1133036&r2=1133037&view=diff
==============================================================================
--- qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java (original)
+++ qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java Tue Jun  7 15:04:42 2011
@@ -37,6 +37,10 @@ import java.lang.ref.WeakReference;
  */
 public final class AMQShortString implements CharSequence, Comparable<AMQShortString>
 {
+    /**
+     * The maximum number of octets in AMQ short string as defined in AMQP specification
+     */
+    public static final int MAX_LENGTH = 255;
     private static final byte MINUS = (byte)'-';
     private static final byte ZERO = (byte) '0';
 
@@ -118,22 +122,19 @@ public final class AMQShortString implem
 
     public AMQShortString(byte[] data)
     {
-
+        if (data == null)
+        {
+            throw new NullPointerException("Cannot create AMQShortString with null data[]");
+        }
+        if (data.length > MAX_LENGTH)
+        {
+            throw new IllegalArgumentException("Cannot create AMQShortString with number of octets over 255!");
+        }
         _data = data.clone();
         _length = data.length;
         _offset = 0;
     }
 
-    public AMQShortString(byte[] data, int pos)
-    {
-        final int size = data[pos++];
-        final byte[] dataCopy = new byte[size];
-        System.arraycopy(data,pos,dataCopy,0,size);
-        _length = size;
-        _data = dataCopy;
-        _offset = 0;
-    }
-
     public AMQShortString(String data)
     {
         this((data == null) ? EMPTY_CHAR_ARRAY : data.toCharArray());
@@ -146,7 +147,12 @@ public final class AMQShortString implem
         {
             throw new NullPointerException("Cannot create AMQShortString with null char[]");
         }
-
+        // the current implementation of 0.8/0.9.x short string encoding
+        // supports only ASCII characters
+        if (data.length> MAX_LENGTH)
+        {
+            throw new IllegalArgumentException("Cannot create AMQShortString with number of octets over 255!");
+        }
         final int length = data.length;
         final byte[] stringBytes = new byte[length];
         int hash = 0;
@@ -165,6 +171,17 @@ public final class AMQShortString implem
 
     public AMQShortString(CharSequence charSequence)
     {
+        if (charSequence == null)
+        {
+            // it should be possible to create short string for null data
+            charSequence = "";
+        }
+        // the current implementation of 0.8/0.9.x short string encoding
+        // supports only ASCII characters
+        if (charSequence.length() > MAX_LENGTH)
+        {
+            throw new IllegalArgumentException("Cannot create AMQShortString with number of octets over 255!");
+        }
         final int length = charSequence.length();
         final byte[] stringBytes = new byte[length];
         int hash = 0;
@@ -184,6 +201,10 @@ public final class AMQShortString implem
 
     private AMQShortString(ByteBuffer data, final int length)
     {
+        if (length > MAX_LENGTH)
+        {
+            throw new IllegalArgumentException("Cannot create AMQShortString with number of octets over 255!");
+        }
         if(data.isDirect() || data.isReadOnly())
         {
             byte[] dataBytes = new byte[length];
@@ -205,8 +226,17 @@ public final class AMQShortString implem
 
     private AMQShortString(final byte[] data, final int from, final int to)
     {
+        if (data == null)
+        {
+            throw new NullPointerException("Cannot create AMQShortString with null data[]");
+        }
+        int length = to - from;
+        if (length > MAX_LENGTH)
+        {
+            throw new IllegalArgumentException("Cannot create AMQShortString with number of octets over 255!");
+        }
         _offset = from;
-        _length = to - from;
+        _length = length;
         _data = data;
     }
 
@@ -245,29 +275,6 @@ public final class AMQShortString implem
         return new CharSubSequence(start, end);
     }
 
-    public int writeToByteArray(byte[] encoding, int pos)
-    {
-        final int size = length();
-        encoding[pos++] = (byte) size;
-        System.arraycopy(_data,_offset,encoding,pos,size);
-        return pos+size;
-    }
-
-    public static AMQShortString readFromByteArray(byte[] byteEncodedDestination, int pos)
-    {
-
-
-        final AMQShortString shortString = new AMQShortString(byteEncodedDestination, pos);
-        if(shortString.length() == 0)
-        {
-            return null;
-        }
-        else
-        {
-            return shortString;
-        }
-    }
-
     public static AMQShortString readFromBuffer(ByteBuffer buffer)
     {
         final short length = buffer.getUnsigned();
@@ -690,6 +697,10 @@ public final class AMQShortString implem
             size += term.length();
         }
 
+        if (size > MAX_LENGTH)
+        {
+            throw new IllegalArgumentException("Cannot create AMQShortString with number of octets over 255!");
+        }
         byte[] data = new byte[size];
         int pos = 0;
         final byte[] delimData = delim._data;

Modified: qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/AMQExceptionTest.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/AMQExceptionTest.java?rev=1133037&r1=1133036&r2=1133037&view=diff
==============================================================================
--- qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/AMQExceptionTest.java (original)
+++ qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/AMQExceptionTest.java Tue Jun  7 15:04:42 2011
@@ -23,6 +23,7 @@ package org.apache.qpid;
 import junit.framework.TestCase;
 import org.apache.qpid.protocol.AMQConstant;
 import org.apache.qpid.framing.AMQFrameDecodingException;
+import org.apache.qpid.framing.AMQShortString;
 
 /**
  * This test is to ensure that when an AMQException is rethrown that the specified exception is correctly wrapped up.
@@ -91,6 +92,18 @@ public class AMQExceptionTest extends Te
         return amqe;
     }
 
+    public void testGetMessageAsString()
+    {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < 25; i++)
+        {
+            sb.append("message [" + i + "]");
+        }
+        AMQException e = new AMQException(AMQConstant.INTERNAL_ERROR, sb.toString(), null);
+        AMQShortString message = e.getMessageAsShortString();
+        assertEquals(sb.substring(0, AMQShortString.MAX_LENGTH - 3) + "...", message.toString());
+    }
+
     /**
      * Private class that extends AMQException but does not have a default exception.
      */

Modified: qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/framing/AMQShortStringTest.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/framing/AMQShortStringTest.java?rev=1133037&r1=1133036&r2=1133037&view=diff
==============================================================================
--- qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/framing/AMQShortStringTest.java (original)
+++ qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/framing/AMQShortStringTest.java Tue Jun  7 15:04:42 2011
@@ -20,6 +20,10 @@
 
 package org.apache.qpid.framing;
 
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+
 import junit.framework.TestCase;
 public class AMQShortStringTest extends TestCase
 {
@@ -105,5 +109,215 @@ public class AMQShortStringTest extends 
         assertFalse(new AMQShortString("A").equals(new AMQShortString("a")));
     }
 
+    /**
+     * Test method for
+     * {@link org.apache.qpid.framing.AMQShortString#AMQShortString(byte[])}.
+     */
+    public void testCreateAMQShortStringByteArray()
+    {
+        byte[] bytes = null;
+        try
+        {
+            bytes = "test".getBytes("UTF-8");
+        }
+        catch (UnsupportedEncodingException e)
+        {
+            fail("UTF-8 encoding is not supported anymore by JVM:" + e.getMessage());
+        }
+        AMQShortString string = new AMQShortString(bytes);
+        assertEquals("constructed amq short string length differs from expected", 4, string.length());
+        assertTrue("constructed amq short string differs from expected", string.equals("test"));
+    }
+
+    /**
+     * Test method for
+     * {@link org.apache.qpid.framing.AMQShortString#AMQShortString(java.lang.String)}
+     * <p>
+     * Tests short string construction from string with length less than 255.
+     */
+    public void testCreateAMQShortStringString()
+    {
+        AMQShortString string = new AMQShortString("test");
+        assertEquals("constructed amq short string length differs from expected", 4, string.length());
+        assertTrue("constructed amq short string differs from expected", string.equals("test"));
+    }
+
+    /**
+     * Test method for
+     * {@link org.apache.qpid.framing.AMQShortString#AMQShortString(char[])}.
+     * <p>
+     * Tests short string construction from char array with length less than 255.
+     */
+    public void testCreateAMQShortStringCharArray()
+    {
+        char[] chars = "test".toCharArray();
+        AMQShortString string = new AMQShortString(chars);
+        assertEquals("constructed amq short string length differs from expected", 4, string.length());
+        assertTrue("constructed amq short string differs from expected", string.equals("test"));
+    }
+
+    /**
+     * Test method for
+     * {@link org.apache.qpid.framing.AMQShortString#AMQShortString(java.lang.CharSequence)}
+     * <p>
+     * Tests short string construction from char sequence with length less than 255.
+     */
+    public void testCreateAMQShortStringCharSequence()
+    {
+        AMQShortString string = new AMQShortString((CharSequence) "test");
+        assertEquals("constructed amq short string length differs from expected", 4, string.length());
+        assertTrue("constructed amq short string differs from expected", string.equals("test"));
+    }
+
+    /**
+     * Test method for
+     * {@link org.apache.qpid.framing.AMQShortString#AMQShortString(byte[])}.
+     * <p>
+     * Tests an attempt to create an AMQP short string from byte array with length over 255.
+     */
+    public void testCreateAMQShortStringByteArrayOver255()
+    {
+        String test = buildString('a', 256);
+        byte[] bytes = null;
+        try
+        {
+            bytes = test.getBytes("UTF-8");
+        }
+        catch (UnsupportedEncodingException e)
+        {
+            fail("UTF-8 encoding is not supported anymore by JVM:" + e.getMessage());
+        }
+        try
+        {
+            new AMQShortString(bytes);
+            fail("It should not be possible to create AMQShortString with length over 255");
+        }
+        catch (IllegalArgumentException e)
+        {
+            assertEquals("Exception message differs from expected",
+                    "Cannot create AMQShortString with number of octets over 255!", e.getMessage());
+        }
+    }
+
+    /**
+     * Test method for
+     * {@link org.apache.qpid.framing.AMQShortString#AMQShortString(java.lang.String)}
+     * <p>
+     * Tests an attempt to create an AMQP short string from string with length over 255
+     */
+    public void testCreateAMQShortStringStringOver255()
+    {
+        String test = buildString('a', 256);
+        try
+        {
+            new AMQShortString(test);
+            fail("It should not be possible to create AMQShortString with length over 255");
+        }
+        catch (IllegalArgumentException e)
+        {
+            assertEquals("Exception message differs from expected",
+                    "Cannot create AMQShortString with number of octets over 255!", e.getMessage());
+        }
+    }
+
+    /**
+     * Test method for
+     * {@link org.apache.qpid.framing.AMQShortString#AMQShortString(char[])}.
+     * <p>
+     * Tests an attempt to create an AMQP short string from char array with length over 255.
+     */
+    public void testCreateAMQShortStringCharArrayOver255()
+    {
+        String test = buildString('a', 256);
+        char[] chars = test.toCharArray();
+        try
+        {
+            new AMQShortString(chars);
+            fail("It should not be possible to create AMQShortString with length over 255");
+        }
+        catch (IllegalArgumentException e)
+        {
+            assertEquals("Exception message differs from expected",
+                    "Cannot create AMQShortString with number of octets over 255!", e.getMessage());
+        }
+    }
+
+    /**
+     * Test method for
+     * {@link org.apache.qpid.framing.AMQShortString#AMQShortString(java.lang.CharSequence)}
+     * <p>
+     * Tests an attempt to create an AMQP short string from char sequence with length over 255.
+     */
+    public void testCreateAMQShortStringCharSequenceOver255()
+    {
+        String test = buildString('a', 256);
+        try
+        {
+            new AMQShortString((CharSequence) test);
+            fail("It should not be possible to create AMQShortString with length over 255");
+        }
+        catch (IllegalArgumentException e)
+        {
+            assertEquals("Exception message differs from expected",
+                    "Cannot create AMQShortString with number of octets over 255!", e.getMessage());
+        }
+    }
+
+    /**
+     * Tests joining of short strings into a short string with length over 255.
+     */
+    public void testJoinOverflow()
+    {
+        List<AMQShortString> data = new ArrayList<AMQShortString>();
+        for (int i = 0; i < 25; i++)
+        {
+            data.add(new AMQShortString("test data!"));
+        }
+        try
+        {
+            AMQShortString.join(data, new AMQShortString(" "));
+            fail("It should not be possible to create AMQShortString with length over 255");
+        }
+        catch (IllegalArgumentException e)
+        {
+            assertEquals("Exception message differs from expected",
+                    "Cannot create AMQShortString with number of octets over 255!", e.getMessage());
+        }
+    }
+
+    /**
+     * Tests joining of short strings into a short string with length less than 255.
+     */
+    public void testJoin()
+    {
+        StringBuilder expected = new StringBuilder();
+        List<AMQShortString> data = new ArrayList<AMQShortString>();
+        data.add(new AMQShortString("test data 1"));
+        expected.append("test data 1");
+        data.add(new AMQShortString("test data 2"));
+        expected.append(" test data 2");
+        AMQShortString result = AMQShortString.join(data, new AMQShortString(" "));
+        assertEquals("join result differs from expected", expected.toString(), result.asString());
+    }
+
+    /**
+     * A helper method to generate a string with given length containing given
+     * character
+     *
+     * @param ch
+     *            char to build string with
+     * @param length
+     *            target string length
+     * @return string
+     */
+    private String buildString(char ch, int length)
+    {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < length; i++)
+        {
+            sb.append(ch);
+        }
+        return sb.toString();
+    }
 
 }



---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:commits-subscribe@qpid.apache.org