summaryrefslogtreecommitdiff
path: root/java/common
diff options
context:
space:
mode:
Diffstat (limited to 'java/common')
-rw-r--r--java/common/src/main/java/org/apache/qpid/AMQChannelException.java3
-rw-r--r--java/common/src/main/java/org/apache/qpid/AMQConnectionException.java3
-rw-r--r--java/common/src/main/java/org/apache/qpid/AMQException.java16
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java83
-rw-r--r--java/common/src/test/java/org/apache/qpid/AMQExceptionTest.java13
-rw-r--r--java/common/src/test/java/org/apache/qpid/framing/AMQShortStringTest.java214
6 files changed, 294 insertions, 38 deletions
diff --git a/java/common/src/main/java/org/apache/qpid/AMQChannelException.java b/java/common/src/main/java/org/apache/qpid/AMQChannelException.java
index ef9420ba87..2f6290b55a 100644
--- a/java/common/src/main/java/org/apache/qpid/AMQChannelException.java
+++ b/java/common/src/main/java/org/apache/qpid/AMQChannelException.java
@@ -54,6 +54,7 @@ public class AMQChannelException extends AMQException
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));
}
+
}
diff --git a/java/common/src/main/java/org/apache/qpid/AMQConnectionException.java b/java/common/src/main/java/org/apache/qpid/AMQConnectionException.java
index 8ef6facef1..ca9c9f9dc4 100644
--- a/java/common/src/main/java/org/apache/qpid/AMQConnectionException.java
+++ b/java/common/src/main/java/org/apache/qpid/AMQConnectionException.java
@@ -62,9 +62,10 @@ public class AMQConnectionException extends AMQException
MethodRegistry reg = MethodRegistry.getMethodRegistry(new ProtocolVersion(major,minor));
return new AMQFrame(0,
reg.createConnectionCloseBody(getErrorCode().getCode(),
- new AMQShortString(getMessage()),
+ getMessageAsShortString(),
_classId,
_methodId));
}
+
}
diff --git a/java/common/src/main/java/org/apache/qpid/AMQException.java b/java/common/src/main/java/org/apache/qpid/AMQException.java
index b0c6fccc9e..86d439d269 100644
--- a/java/common/src/main/java/org/apache/qpid/AMQException.java
+++ b/java/common/src/main/java/org/apache/qpid/AMQException.java
@@ -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 Exception
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);
+ }
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java b/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java
index 39a9beb9e8..2b9e2ffaba 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java
@@ -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 implements CharSequence, Comparable<AMQShortSt
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 implements CharSequence, Comparable<AMQShortSt
{
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 implements CharSequence, Comparable<AMQShortSt
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 implements CharSequence, Comparable<AMQShortSt
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 implements CharSequence, Comparable<AMQShortSt
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 implements CharSequence, Comparable<AMQShortSt
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 implements CharSequence, Comparable<AMQShortSt
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;
diff --git a/java/common/src/test/java/org/apache/qpid/AMQExceptionTest.java b/java/common/src/test/java/org/apache/qpid/AMQExceptionTest.java
index ef6cd41492..f65427e583 100644
--- a/java/common/src/test/java/org/apache/qpid/AMQExceptionTest.java
+++ b/java/common/src/test/java/org/apache/qpid/AMQExceptionTest.java
@@ -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 TestCase
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.
*/
diff --git a/java/common/src/test/java/org/apache/qpid/framing/AMQShortStringTest.java b/java/common/src/test/java/org/apache/qpid/framing/AMQShortStringTest.java
index 92e7ce0a80..9a805d87b3 100644
--- a/java/common/src/test/java/org/apache/qpid/framing/AMQShortStringTest.java
+++ b/java/common/src/test/java/org/apache/qpid/framing/AMQShortStringTest.java
@@ -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 TestCase
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();
+ }
}