summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
Diffstat (limited to 'java')
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQDestination.java112
-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
7 files changed, 299 insertions, 145 deletions
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java b/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java
index eb9682a3cf..3ef32fb008 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java
@@ -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 implements Destination, Referenceable
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 implements Destination, Referenceable
{
if(_urlAsShortString == null)
{
- toURL();
+ if (_url == null)
+ {
+ toURL();
+ }
+ _urlAsShortString = new AMQShortString(_url);
}
return _urlAsShortString;
}
@@ -370,7 +365,6 @@ public abstract class AMQDestination implements Destination, Referenceable
// calculated URL now out of date
_url = null;
_urlAsShortString = null;
- _byteEncoding = null;
}
public AMQShortString getRoutingKey()
@@ -508,59 +502,10 @@ public abstract class AMQDestination implements Destination, Referenceable
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 implements Destination, Referenceable
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();
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();
+ }
}