diff options
author | Martin Ritchie <ritchiem@apache.org> | 2006-12-15 08:33:10 +0000 |
---|---|---|
committer | Martin Ritchie <ritchiem@apache.org> | 2006-12-15 08:33:10 +0000 |
commit | a96152eea7e7ce48bb9340f477f3935744ee5ea6 (patch) | |
tree | ada0a6c314add42f32e5143e298c010ecc4b997c | |
parent | b6e573a5889ff89ccceeab3d3dc0504157a8c285 (diff) | |
download | qpid-python-a96152eea7e7ce48bb9340f477f3935744ee5ea6.tar.gz |
QPID-181 QPID-180
AbstractJMSMessage.java - updated to use getJMSHeaders
JMSMapMessage.java - JMSPropertyFieldTable.java - Moved functionality of setting and retrieving a JMS property. Now shared by the Headers and MapMessageTest.java
MapMessageTest.java - Updated the exceptions that are caught as all methods should throw a JMSException i.e. MessageFormatException
TextMessageTest.java - Added tests for the Message Properties
common/pom.xml - Added JMS dependency for the JMSPropertyFieldTable.java and associated tests
EncodingUtils.java - changed comments and changed getencodedCharLength return to an int
PropertyFieldTable.java - Cleaned up and now uses enum for prefixs. Created comprehensive test of both PropertyFieldTable classes.
AMQPInvalidClassException.java - created to throw a runtime exception when trying to add a non-primative value. Forcing clients to handle this would break the Map usage of the FieldTable.
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@487481 13f79535-47bb-0310-9956-ffa450edef68
14 files changed, 3077 insertions, 847 deletions
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java index c1ed88b167..978b74e789 100644 --- a/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java +++ b/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java @@ -32,11 +32,13 @@ import org.apache.qpid.client.AMQTopic; import org.apache.qpid.client.JmsNotImplementedException; import org.apache.qpid.framing.BasicContentHeaderProperties; import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.framing.JMSPropertyFieldTable; import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.MessageNotReadableException; import javax.jms.MessageNotWriteableException; +import javax.jms.MessageFormatException; import java.util.Collections; import java.util.Enumeration; import java.util.Map; @@ -234,7 +236,7 @@ public abstract class AbstractJMSMessage extends AMQMessage implements javax.jms public void clearProperties() throws JMSException { - getJmsContentHeaderProperties().getHeaders().clear(); + getJmsContentHeaderProperties().getJMSHeaders().clear(); _readableProperties = false; } @@ -249,135 +251,136 @@ public abstract class AbstractJMSMessage extends AMQMessage implements javax.jms public boolean propertyExists(String propertyName) throws JMSException { checkPropertyName(propertyName); - return getJmsContentHeaderProperties().getHeaders().propertyExists(propertyName); + return getJmsContentHeaderProperties().getJMSHeaders().propertyExists(propertyName); } public boolean getBooleanProperty(String propertyName) throws JMSException { checkPropertyName(propertyName); - return getJmsContentHeaderProperties().getHeaders().getBoolean(propertyName); + + return getJmsContentHeaderProperties().getJMSHeaders().getBoolean(propertyName); } public byte getByteProperty(String propertyName) throws JMSException { checkPropertyName(propertyName); - return getJmsContentHeaderProperties().getHeaders().getByte(propertyName); + return getJmsContentHeaderProperties().getJMSHeaders().getByte(propertyName); } public short getShortProperty(String propertyName) throws JMSException { checkPropertyName(propertyName); - return getJmsContentHeaderProperties().getHeaders().getShort(propertyName); + return getJmsContentHeaderProperties().getJMSHeaders().getShort(propertyName); } public int getIntProperty(String propertyName) throws JMSException { checkPropertyName(propertyName); - return getJmsContentHeaderProperties().getHeaders().getInteger(propertyName); + return getJmsContentHeaderProperties().getJMSHeaders().getInteger(propertyName); } public long getLongProperty(String propertyName) throws JMSException { checkPropertyName(propertyName); - return getJmsContentHeaderProperties().getHeaders().getLong(propertyName); + return getJmsContentHeaderProperties().getJMSHeaders().getLong(propertyName); } public float getFloatProperty(String propertyName) throws JMSException { checkPropertyName(propertyName); - return getJmsContentHeaderProperties().getHeaders().getFloat(propertyName); + return getJmsContentHeaderProperties().getJMSHeaders().getFloat(propertyName); } public double getDoubleProperty(String propertyName) throws JMSException { checkPropertyName(propertyName); - return getJmsContentHeaderProperties().getHeaders().getDouble(propertyName); + return getJmsContentHeaderProperties().getJMSHeaders().getDouble(propertyName); } public String getStringProperty(String propertyName) throws JMSException { checkPropertyName(propertyName); - return getJmsContentHeaderProperties().getHeaders().getString(propertyName); + return getJmsContentHeaderProperties().getJMSHeaders().getString(propertyName); } public Object getObjectProperty(String propertyName) throws JMSException { checkPropertyName(propertyName); - return getJmsContentHeaderProperties().getHeaders().getObject(propertyName); + return getJmsContentHeaderProperties().getJMSHeaders().getObject(propertyName); } public Enumeration getPropertyNames() throws JMSException { - return getJmsContentHeaderProperties().getHeaders().getPropertyNames(); + return getJmsContentHeaderProperties().getJMSHeaders().getPropertyNames(); } public void setBooleanProperty(String propertyName, boolean b) throws JMSException { checkWritableProperties(); checkPropertyName(propertyName); - getJmsContentHeaderProperties().getHeaders().setBoolean(propertyName, b); + getJmsContentHeaderProperties().getJMSHeaders().setBoolean(propertyName, b); } public void setByteProperty(String propertyName, byte b) throws JMSException { checkWritableProperties(); checkPropertyName(propertyName); - getJmsContentHeaderProperties().getHeaders().setByte(propertyName, new Byte(b)); + getJmsContentHeaderProperties().getJMSHeaders().setByte(propertyName, new Byte(b)); } public void setShortProperty(String propertyName, short i) throws JMSException { checkWritableProperties(); checkPropertyName(propertyName); - getJmsContentHeaderProperties().getHeaders().setShort(propertyName, new Short(i)); + getJmsContentHeaderProperties().getJMSHeaders().setShort(propertyName, new Short(i)); } public void setIntProperty(String propertyName, int i) throws JMSException { checkWritableProperties(); checkPropertyName(propertyName); - getJmsContentHeaderProperties().getHeaders().setInteger(propertyName, new Integer(i)); + getJmsContentHeaderProperties().getJMSHeaders().setInteger(propertyName, new Integer(i)); } public void setLongProperty(String propertyName, long l) throws JMSException { checkWritableProperties(); checkPropertyName(propertyName); - getJmsContentHeaderProperties().getHeaders().setLong(propertyName, new Long(l)); + getJmsContentHeaderProperties().getJMSHeaders().setLong(propertyName, new Long(l)); } public void setFloatProperty(String propertyName, float f) throws JMSException { checkWritableProperties(); checkPropertyName(propertyName); - getJmsContentHeaderProperties().getHeaders().setFloat(propertyName, new Float(f)); + getJmsContentHeaderProperties().getJMSHeaders().setFloat(propertyName, new Float(f)); } public void setDoubleProperty(String propertyName, double v) throws JMSException { checkWritableProperties(); checkPropertyName(propertyName); - getJmsContentHeaderProperties().getHeaders().setDouble(propertyName, new Double(v)); + getJmsContentHeaderProperties().getJMSHeaders().setDouble(propertyName, new Double(v)); } public void setStringProperty(String propertyName, String value) throws JMSException { checkWritableProperties(); checkPropertyName(propertyName); - getJmsContentHeaderProperties().getHeaders().setString(propertyName, value); + getJmsContentHeaderProperties().getJMSHeaders().setString(propertyName, value); } public void setObjectProperty(String propertyName, Object object) throws JMSException { checkWritableProperties(); checkPropertyName(propertyName); - getJmsContentHeaderProperties().getHeaders().setObject(propertyName, object); + getJmsContentHeaderProperties().getJMSHeaders().setObject(propertyName, object); } protected void removeProperty(String propertyName) throws JMSException { checkPropertyName(propertyName); - getJmsContentHeaderProperties().getHeaders().remove(propertyName); + getJmsContentHeaderProperties().getJMSHeaders().remove(propertyName); } public void acknowledge() throws JMSException @@ -426,13 +429,13 @@ public abstract class AbstractJMSMessage extends AMQMessage implements javax.jms buf.append("\nJMS reply to: ").append(String.valueOf(getJMSReplyTo())); buf.append("\nAMQ message number: ").append(_deliveryTag); buf.append("\nProperties:"); - if (getJmsContentHeaderProperties().getHeaders().isEmpty()) + if (getJmsContentHeaderProperties().getJMSHeaders().isEmpty()) { buf.append("<NONE>"); } else { - buf.append('\n').append(getJmsContentHeaderProperties().getHeaders()); + buf.append('\n').append(getJmsContentHeaderProperties().getJMSHeaders()); } return buf.toString(); } @@ -462,9 +465,6 @@ public abstract class AbstractJMSMessage extends AMQMessage implements javax.jms { throw new IllegalArgumentException("Property name must not be the empty string"); } - - // Call to ensure that the it has been set. - getJmsContentHeaderProperties().getHeaders(); } public BasicContentHeaderProperties getJmsContentHeaderProperties() diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessage.java index 1f084b8de3..fccce92dee 100644 --- a/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessage.java +++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessage.java @@ -25,6 +25,8 @@ import org.apache.qpid.framing.PropertyFieldTable; import org.apache.qpid.framing.FieldTableFactory; import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.EncodingUtils; +import org.apache.qpid.framing.JMSPropertyFieldTable; +import org.apache.qpid.framing.AMQFrameDecodingException; import org.apache.qpid.AMQException; import org.apache.log4j.Logger; @@ -39,7 +41,7 @@ public class JMSMapMessage extends JMSBytesMessage implements javax.jms.MapMessa public static final String MIME_TYPE = "jms/map-message"; - private PropertyFieldTable _map; + private JMSPropertyFieldTable _properties; JMSMapMessage() throws JMSException { @@ -49,16 +51,9 @@ public class JMSMapMessage extends JMSBytesMessage implements javax.jms.MapMessa JMSMapMessage(ByteBuffer data) throws JMSException { super(data); // this instantiates a content header - _map = new PropertyFieldTable(); + _properties = new JMSPropertyFieldTable(); } - - @Override - public void clearBodyImpl() throws JMSException { - super.clearBodyImpl(); - _map = new PropertyFieldTable(); - } - JMSMapMessage(long messageNbr, ContentHeaderBody contentHeader, ByteBuffer data) throws AMQException { @@ -68,19 +63,33 @@ public class JMSMapMessage extends JMSBytesMessage implements javax.jms.MapMessa { long tableSize = EncodingUtils.readInteger(_data); - _map = (PropertyFieldTable) FieldTableFactory.newFieldTable(_data, tableSize); - + try + { + _properties = new JMSPropertyFieldTable(_data, tableSize); + } + catch (JMSException e) + { + Exception error = e.getLinkedException(); + if (error instanceof AMQFrameDecodingException) + { + throw(AMQFrameDecodingException) error; + } + else + { + throw new AMQException(e.getMessage(), e); + } + } } else { - _map = (PropertyFieldTable) FieldTableFactory.newFieldTable(); + _properties = new JMSPropertyFieldTable(); } } public String toBodyString() throws JMSException { - return "MapSize:" + _map.getEncodedSize() + "\nMapData:\n" + _map.toString(); + return _properties.toString(); } public String getMimeType() @@ -88,81 +97,40 @@ public class JMSMapMessage extends JMSBytesMessage implements javax.jms.MapMessa return MIME_TYPE; } - // MapMessage Interface - public boolean getBoolean(String string) throws JMSException + public ByteBuffer getData() { - Boolean b = _map.getBoolean(string); - - if (b == null) - { - if (_map.containsKey(string)) - { - Object str = _map.getObject(string); + //What if _data is null? + _properties.writeToBuffer(_data); + return super.getData(); + } - if (str == null || !(str instanceof String)) - { - throw new MessageFormatException("getBoolean can't use " + string + " item."); - } - else - { - return Boolean.valueOf((String) str); - } - } - else - { - b = Boolean.valueOf(null); - } - } + @Override + public void clearBodyImpl() throws JMSException + { + super.clearBodyImpl(); + _properties.clear(); + } - return b; + public boolean getBoolean(String string) throws JMSException + { + return _properties.getBoolean(string); } public byte getByte(String string) throws JMSException { - Byte b = _map.getByte(string); - if (b == null) - { - if (_map.containsKey(string)) - { - Object str = _map.getObject(string); - - if (str == null || !(str instanceof String)) - { - throw new MessageFormatException("getByte can't use " + string + " item."); - } - else - { - return Byte.valueOf((String) str); - } - } - else - { - b = Byte.valueOf(null); - } - } - - return b; + return _properties.getByte(string); } public short getShort(String string) throws JMSException { - { - Short s = _map.getShort(string); - - if (s == null) - { - s = Short.valueOf(getByte(string)); - } - - return s; - } + return _properties.getShort(string); } public char getChar(String string) throws JMSException { - Character result = _map.getCharacter(string); + Character result = _properties.getCharacter(string); if (result == null) { @@ -176,179 +144,97 @@ public class JMSMapMessage extends JMSBytesMessage implements javax.jms.MapMessa public int getInt(String string) throws JMSException { - Integer i = _map.getInteger(string); - - if (i == null) - { - i = Integer.valueOf(getShort(string)); - } - - return i; + return _properties.getInteger(string); } public long getLong(String string) throws JMSException { - - Long l = _map.getLong(string); - - if (l == null) - { - l = Long.valueOf(getInt(string)); - } - - return l; - + return _properties.getLong(string); } public float getFloat(String string) throws JMSException { - - Float f = _map.getFloat(string); - - if (f == null) - { - if (_map.containsKey(string)) - { - Object str = _map.getObject(string); - - if (str == null || !(str instanceof String)) - { - throw new MessageFormatException("getFloat can't use " + string + " item."); - } - else - { - return Float.valueOf((String) str); - } - } - else - { - f = Float.valueOf(null); - } - - } - - return f; - + return _properties.getFloat(string); } public double getDouble(String string) throws JMSException { - Double d = _map.getDouble(string); - - if (d == null) - { - d = Double.valueOf(getFloat(string)); - } - - return d; + return _properties.getDouble(string); } public String getString(String string) throws JMSException { - String s = _map.getString(string); - - if (s == null) - { - if (_map.containsKey(string)) - { - Object o = _map.getObject(string); - if (o instanceof byte[]) - { - throw new MessageFormatException("getObject couldn't find " + string + " item."); - } - else - { - if (o == null) - { - return null; - } - else - { - s = String.valueOf(o); - } - } - } - } - - return s; + return _properties.getString(string); } public byte[] getBytes(String string) throws JMSException { - - byte[] result = _map.getBytes(string); - - if (result == null) - { - throw new MessageFormatException("getBytes couldn't find " + string + " item."); - } - - return result; - + return _properties.getBytes(string); } public Object getObject(String string) throws JMSException { - return _map.getObject(string); + return _properties.getObject(string); } public Enumeration getMapNames() throws JMSException { - return _map.getPropertyNames(); + return _properties.getMapNames(); } + public void setBoolean(String string, boolean b) throws JMSException { checkWritable(); - _map.setBoolean(string, b); + _properties.setBoolean(string, b); } public void setByte(String string, byte b) throws JMSException { checkWritable(); - _map.setByte(string, b); + _properties.setByte(string, b); } public void setShort(String string, short i) throws JMSException { checkWritable(); - _map.setShort(string, i); + _properties.setShort(string, i); } public void setChar(String string, char c) throws JMSException { checkWritable(); - _map.setChar(string, c); + _properties.setChar(string, c); } public void setInt(String string, int i) throws JMSException { checkWritable(); - _map.setInteger(string, i); + _properties.setInteger(string, i); } public void setLong(String string, long l) throws JMSException { checkWritable(); - _map.setLong(string, l); + _properties.setLong(string, l); } public void setFloat(String string, float v) throws JMSException { checkWritable(); - _map.setFloat(string, v); + _properties.setFloat(string, v); } public void setDouble(String string, double v) throws JMSException { checkWritable(); - _map.setDouble(string, v); + _properties.setDouble(string, v); } public void setString(String string, String string1) throws JMSException { checkWritable(); - _map.setString(string, string1); + _properties.setString(string, string1); } public void setBytes(String string, byte[] bytes) throws JMSException @@ -359,25 +245,18 @@ public class JMSMapMessage extends JMSBytesMessage implements javax.jms.MapMessa public void setBytes(String string, byte[] bytes, int i, int i1) throws JMSException { checkWritable(); - _map.setBytes(string, bytes, i, i1); + _properties.setBytes(string, bytes, i, i1); } public void setObject(String string, Object object) throws JMSException { checkWritable(); - _map.setObject(string, object); + _properties.setObject(string, object); } public boolean itemExists(String string) throws JMSException { - return _map.itemExists(string); - } - - public ByteBuffer getData() - { - //What if _data is null? - _map.writeToBuffer(_data); - return super.getData(); + return _properties.itemExists(string); } } diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/MapMessageTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/basic/MapMessageTest.java index 1a469c1d12..823406daa4 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/MapMessageTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/basic/MapMessageTest.java @@ -166,12 +166,12 @@ public class MapMessageTest extends TestCase implements MessageListener testMapValues(m, count); - testMessageWriteStatus(m); - testPropertyWriteStatus(m); testCorrectExceptions(m); + testMessageWriteStatus(m); + count++; } } @@ -207,9 +207,9 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getByte("message"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } - catch (NumberFormatException nfe) + catch (MessageFormatException nfe) { //normal execution } @@ -217,9 +217,9 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getShort("message"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } - catch (NumberFormatException nfe) + catch (MessageFormatException nfe) { //normal execution } @@ -228,7 +228,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getChar("message"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -238,18 +238,18 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getInt("message"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } - catch (NumberFormatException nfe) + catch (MessageFormatException nfe) { //normal execution } try { m.getLong("message"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } - catch (NumberFormatException nfe) + catch (MessageFormatException nfe) { //normal execution } @@ -258,9 +258,9 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getFloat("message"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } - catch (NumberFormatException nfe) + catch (MessageFormatException nfe) { //normal execution } @@ -268,9 +268,9 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getDouble("message"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } - catch (NumberFormatException nfe) + catch (MessageFormatException nfe) { //normal execution } @@ -278,7 +278,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getBytes("message"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -295,7 +295,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getBoolean("short"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -305,7 +305,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getByte("short"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -318,7 +318,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getChar("short"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -333,7 +333,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getFloat("short"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -343,7 +343,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getDouble("short"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -353,7 +353,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getBytes("short"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -370,7 +370,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getBoolean("long"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -380,7 +380,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getByte("long"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -390,7 +390,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getShort("long"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -401,7 +401,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getChar("long"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -411,7 +411,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getInt("long"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -424,7 +424,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getFloat("long"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -434,7 +434,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getDouble("long"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -444,7 +444,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getBytes("long"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -461,7 +461,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getBoolean("double"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -471,7 +471,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getByte("double"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -481,7 +481,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getShort("double"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -492,7 +492,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getChar("double"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -502,7 +502,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getInt("double"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -511,7 +511,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getLong("double"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -522,7 +522,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getFloat("double"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -536,7 +536,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getBytes("double"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -554,7 +554,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getBoolean("float"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -564,7 +564,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getByte("float"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -574,7 +574,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getShort("float"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -585,7 +585,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getChar("float"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -595,7 +595,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getInt("float"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -604,7 +604,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getLong("float"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -620,7 +620,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getBytes("float"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -638,7 +638,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getBoolean("int"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -648,7 +648,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getByte("int"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -658,7 +658,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getShort("int"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -669,7 +669,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getChar("int"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -684,7 +684,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getFloat("int"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -694,7 +694,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getDouble("int"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -704,7 +704,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getBytes("int"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -722,7 +722,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getBoolean("char"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -732,7 +732,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getByte("char"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -742,7 +742,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getShort("char"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -754,7 +754,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getInt("char"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -763,7 +763,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getLong("char"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -774,7 +774,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getFloat("char"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -784,7 +784,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getDouble("char"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -794,7 +794,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getBytes("char"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -810,7 +810,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getBoolean("bytes"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -820,7 +820,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getByte("bytes"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -830,7 +830,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getShort("bytes"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -841,7 +841,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getChar("bytes"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -851,7 +851,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getInt("bytes"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -861,7 +861,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getLong("bytes"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -872,7 +872,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getFloat("bytes"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -882,7 +882,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getDouble("bytes"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -895,7 +895,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getString("bytes"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -911,7 +911,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getBoolean("byte"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -926,7 +926,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getChar("byte"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -942,7 +942,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getFloat("byte"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -952,7 +952,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getDouble("byte"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -962,7 +962,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getBytes("byte"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -982,7 +982,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getByte("odd"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -993,7 +993,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getShort("odd"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -1003,9 +1003,9 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getChar("odd"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } - catch (MessageFormatException nfe) + catch (MessageFormatException npe) { //normal execution } @@ -1013,7 +1013,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getInt("odd"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -1023,7 +1023,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getLong("odd"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -1033,7 +1033,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getFloat("odd"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -1043,7 +1043,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getDouble("odd"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -1053,7 +1053,7 @@ public class MapMessageTest extends TestCase implements MessageListener try { m.getBytes("odd"); - fail("Exception Expected."); + fail("MessageFormatException expected as value doesn't exist."); } catch (MessageFormatException nfe) { @@ -1224,7 +1224,6 @@ public class MapMessageTest extends TestCase implements MessageListener { synchronized(received) { - _logger.info("****************** Recevied Messgage:" + (JMSMapMessage) message); received.add((JMSMapMessage) message); received.notify(); } diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/message/MapMessageTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/client/message/MapMessageTest.java index e5458fd89e..58e62e8252 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/client/message/MapMessageTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/client/message/MapMessageTest.java @@ -206,7 +206,7 @@ public class MapMessageTest extends TestCase mm.getByte("random"); Assert.fail("MessageFormatException expected"); } - catch (NumberFormatException e) + catch (MessageFormatException e) { //normal execution } @@ -295,9 +295,9 @@ public class MapMessageTest extends TestCase { JMSMapMessage mm = TestMessageHelper.newJMSMapMessage(); mm.getInt("random"); - Assert.fail("NumberFormatException should be received."); + Assert.fail("MessageFormatException should be received."); } - catch (NumberFormatException e) + catch (MessageFormatException e) { //normal execution } @@ -313,9 +313,9 @@ public class MapMessageTest extends TestCase { JMSMapMessage mm = TestMessageHelper.newJMSMapMessage(); mm.getLong("random"); - Assert.fail("NumberFormatException should be received."); + Assert.fail("MessageFormatException should be received."); } - catch (NumberFormatException e) + catch (MessageFormatException e) { //normal execution } @@ -331,9 +331,9 @@ public class MapMessageTest extends TestCase { JMSMapMessage mm = TestMessageHelper.newJMSMapMessage(); mm.getShort("random"); - Assert.fail("NumberFormatException should be received."); + Assert.fail("MessageFormatException should be received."); } - catch (NumberFormatException e) + catch (MessageFormatException e) { //normal execution } diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/message/TextMessageTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/client/message/TextMessageTest.java index 337b0f3bbc..1345c0defb 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/client/message/TextMessageTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/client/message/TextMessageTest.java @@ -22,8 +22,13 @@ package org.apache.qpid.test.unit.client.message; import org.apache.qpid.client.message.TestMessageHelper; import org.apache.qpid.client.message.JMSTextMessage; +import org.apache.qpid.client.message.JMSMapMessage; import junit.framework.TestCase; +import junit.framework.Assert; + +import javax.jms.JMSException; +import javax.jms.MessageFormatException; public class TextMessageTest extends TestCase { @@ -47,6 +52,248 @@ public class TextMessageTest extends TestCase assertEquals(val, "Banana"); } + + public void testBooleanPropertyLookup() + { + try + { + JMSTextMessage tm = TestMessageHelper.newJMSTextMessage(); + + tm.setBooleanProperty("value", true); + Assert.assertEquals(true, tm.getBooleanProperty("value")); + Assert.assertEquals("true", tm.getStringProperty("value")); + } + catch (JMSException e) + { + Assert.fail("JMSException received." + e); + } + } + + public void testBytePropertyLookup() + { + try + { + JMSMapMessage mm = TestMessageHelper.newJMSMapMessage(); + mm.setByteProperty("value", Byte.MAX_VALUE); + + Assert.assertEquals(Byte.MAX_VALUE, mm.getByteProperty("value")); + Assert.assertEquals((short) Byte.MAX_VALUE, mm.getShortProperty("value")); + Assert.assertEquals(Byte.MAX_VALUE, mm.getIntProperty("value")); + Assert.assertEquals((long) Byte.MAX_VALUE, mm.getLongProperty("value")); + Assert.assertEquals("" + Byte.MAX_VALUE, mm.getStringProperty("value")); + + } + catch (JMSException e) + { + Assert.fail("JMSException received." + e); + } + } + + public void testShortPropertyLookup() + { + try + { + JMSMapMessage mm = TestMessageHelper.newJMSMapMessage(); + mm.setShortProperty("value", Short.MAX_VALUE); + Assert.assertEquals(Short.MAX_VALUE, mm.getShortProperty("value")); + Assert.assertEquals((int) Short.MAX_VALUE, mm.getIntProperty("value")); + Assert.assertEquals((long) Short.MAX_VALUE, mm.getLongProperty("value")); + Assert.assertEquals("" + Short.MAX_VALUE, mm.getStringProperty("value")); + } + catch (JMSException e) + { + Assert.fail("JMSException received." + e); + } + } + + public void testDoublePropertyLookup() + { + try + { + JMSMapMessage mm = TestMessageHelper.newJMSMapMessage(); + mm.setDoubleProperty("value", Double.MAX_VALUE); + Assert.assertEquals(Double.MAX_VALUE, mm.getDoubleProperty("value")); + Assert.assertEquals("" + Double.MAX_VALUE, mm.getStringProperty("value")); + } + catch (JMSException e) + { + Assert.fail("JMSException received." + e); + } + } + + public void testFloatPropertyLookup() + { + try + { + JMSMapMessage mm = TestMessageHelper.newJMSMapMessage(); + mm.setFloatProperty("value", Float.MAX_VALUE); + Assert.assertEquals(Float.MAX_VALUE, mm.getFloatProperty("value")); + Assert.assertEquals((double) Float.MAX_VALUE, mm.getDoubleProperty("value")); + Assert.assertEquals("" + Float.MAX_VALUE, mm.getStringProperty("value")); + } + catch (JMSException e) + { + Assert.fail("JMSException received." + e); + } + } + + public void testIntPropertyLookup() + { + try + { + JMSMapMessage mm = TestMessageHelper.newJMSMapMessage(); + mm.setIntProperty("value", Integer.MAX_VALUE); + Assert.assertEquals(Integer.MAX_VALUE, mm.getIntProperty("value")); + Assert.assertEquals((long) Integer.MAX_VALUE, mm.getLongProperty("value")); + Assert.assertEquals("" + Integer.MAX_VALUE, mm.getStringProperty("value")); + } + catch (JMSException e) + { + Assert.fail("JMSException received." + e); + } + } + + public void testLongPropertyLookup() + { + try + { + JMSMapMessage mm = TestMessageHelper.newJMSMapMessage(); + mm.setLongProperty("value", Long.MAX_VALUE); + Assert.assertEquals(Long.MAX_VALUE, mm.getLongProperty("value")); + Assert.assertEquals("" + Long.MAX_VALUE, mm.getStringProperty("value")); + } + catch (JMSException e) + { + Assert.fail("JMSException received." + e); + } + } + + + // Failed Lookups + + public void testFailedBooleanPropertyLookup() + { + try + { + JMSMapMessage mm = TestMessageHelper.newJMSMapMessage(); + Assert.assertEquals(false, mm.getBooleanProperty("int")); + } + catch (JMSException e) + { + Assert.fail("JMSException received." + e); + } + } + + public void testFailedBytePropertyLookup() + { + try + { + JMSMapMessage mm = TestMessageHelper.newJMSMapMessage(); + mm.getByteProperty("random"); + Assert.fail("MessageFormatException expected"); + } + catch (MessageFormatException e) + { + //normal execution + } + catch (JMSException e) + { + Assert.fail("JMSException received:" + e); + } + + } + + public void testFailedDoublePropertyLookup() + { + try + { + JMSMapMessage mm = TestMessageHelper.newJMSMapMessage(); + mm.getDoubleProperty("random"); + Assert.fail("NullPointerException should be received."); + } + catch (NullPointerException e) + { + //normal execution + } + catch (JMSException e) + { + Assert.fail("JMSException received:" + e); + } + } + + public void testFailedFloatPropertyLookup() + { + try + { + JMSMapMessage mm = TestMessageHelper.newJMSMapMessage(); + mm.getFloatProperty("random"); + Assert.fail("NullPointerException should be received."); + } + catch (NullPointerException e) + { + //normal execution + } + catch (JMSException e) + { + Assert.fail("JMSException received:" + e); + } + } + + public void testFailedIntPropertyLookup() + { + try + { + JMSMapMessage mm = TestMessageHelper.newJMSMapMessage(); + mm.getIntProperty("random"); + Assert.fail("MessageFormatException should be received."); + } + catch (MessageFormatException e) + { + //normal execution + } + catch (JMSException e) + { + Assert.fail("JMSException received:" + e); + } + } + + public void testFailedLongPropertyLookup() + { + try + { + JMSMapMessage mm = TestMessageHelper.newJMSMapMessage(); + mm.getLongProperty("random"); + Assert.fail("MessageFormatException should be received."); + } + catch (MessageFormatException e) + { + //normal execution + } + catch (JMSException e) + { + Assert.fail("JMSException received:" + e); + } + } + + public void testFailedShortPropertyLookup() + { + try + { + JMSMapMessage mm = TestMessageHelper.newJMSMapMessage(); + mm.getShortProperty("random"); + Assert.fail("MessageFormatException should be received."); + } + catch (MessageFormatException e) + { + //normal execution + } + catch (JMSException e) + { + Assert.fail("JMSException received:" + e); + } + } + + public static junit.framework.Test suite() { return new junit.framework.TestSuite(TextMessageTest.class); diff --git a/java/common/pom.xml b/java/common/pom.xml index bbc70bf7f6..653b2a8a9d 100644 --- a/java/common/pom.xml +++ b/java/common/pom.xml @@ -90,5 +90,9 @@ <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> + <dependency> + <groupId>org.apache.geronimo.specs</groupId> + <artifactId>geronimo-jms_1.1_spec</artifactId> + </dependency> </dependencies> </project> diff --git a/java/common/src/main/java/org/apache/qpid/AMQPInvalidClassException.java b/java/common/src/main/java/org/apache/qpid/AMQPInvalidClassException.java new file mode 100644 index 0000000000..883e13e5e6 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/AMQPInvalidClassException.java @@ -0,0 +1,30 @@ +/* + * 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.qpid; + + +public class AMQPInvalidClassException extends RuntimeException +{ + public AMQPInvalidClassException(String s) + { + super(s); + } +} diff --git a/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java b/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java index a908c76286..61837f65cc 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java +++ b/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java @@ -57,6 +57,8 @@ public class BasicContentHeaderProperties implements ContentHeaderProperties private FieldTable _headers; + private JMSPropertyFieldTable _jmsHeaders; + private byte _deliveryMode; private byte _priority; @@ -276,6 +278,7 @@ public class BasicContentHeaderProperties implements ContentHeaderProperties if ((_propertyFlags & (1 << 13)) > 0) { _headers = EncodingUtils.readFieldTable(buffer); + setJMSHeaders(); } if ((_propertyFlags & (1 << 12)) > 0) { @@ -358,6 +361,8 @@ public class BasicContentHeaderProperties implements ContentHeaderProperties if ((_propertyFlags & (1 << 13)) > 0) { _headers = EncodingUtils.readFieldTable(buffer); + setJMSHeaders(); + } _decodedHeaders = true; } @@ -446,6 +451,26 @@ public class BasicContentHeaderProperties implements ContentHeaderProperties clearEncodedForm(); _propertyFlags |= (1 << 13); _headers = headers; + setJMSHeaders(); + } + + private void setJMSHeaders() + { + if (_jmsHeaders == null) + { + _jmsHeaders = new JMSPropertyFieldTable(_headers); + } + else + { + _jmsHeaders.setFieldTable(_headers); + } + } + + public JMSPropertyFieldTable getJMSHeaders() + { + //This will ensure we have a blank header + getHeaders(); + return _jmsHeaders; } public byte getDeliveryMode() diff --git a/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java b/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java index 61a0787fcd..46dff9ffa8 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java +++ b/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java @@ -461,7 +461,7 @@ public class EncodingUtils //**** new methods - // BOOLEAN_PROPERTY_PREFIX + // AMQP_BOOLEAN_PROPERTY_PREFIX public static void writeBoolean(ByteBuffer buffer, Boolean aBoolean) { @@ -479,7 +479,7 @@ public class EncodingUtils return 1; } - // BYTE_PROPERTY_PREFIX + // AMQP_BYTE_PROPERTY_PREFIX public static void writeByte(ByteBuffer buffer, Byte aByte) { buffer.put(aByte); @@ -496,7 +496,7 @@ public class EncodingUtils } - // SHORT_PROPERTY_PREFIX + // AMQP_SHORT_PROPERTY_PREFIX public static void writeShort(ByteBuffer buffer, Short aShort) { buffer.putShort(aShort); @@ -528,7 +528,7 @@ public class EncodingUtils return 4; } - // LONG_PROPERTY_PREFIX + // AMQP_LONG_PROPERTY_PREFIX public static void writeLong(ByteBuffer buffer, Long aLong) { buffer.putLong(aLong); @@ -610,7 +610,7 @@ public class EncodingUtils } //CHAR_PROPERTY - public static long encodedCharLength() + public static int encodedCharLength() { return encodedByteLength(); } diff --git a/java/common/src/main/java/org/apache/qpid/framing/JMSPropertyFieldTable.java b/java/common/src/main/java/org/apache/qpid/framing/JMSPropertyFieldTable.java new file mode 100644 index 0000000000..cc56e7c4de --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/framing/JMSPropertyFieldTable.java @@ -0,0 +1,514 @@ +/* + * 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.qpid.framing; + +import org.apache.mina.common.ByteBuffer; +import org.apache.qpid.AMQPInvalidClassException; + +import javax.jms.MessageFormatException; +import javax.jms.JMSException; +import java.util.Enumeration; + + +public class JMSPropertyFieldTable +{ + private FieldTable _fieldtable; + + public JMSPropertyFieldTable() + { + _fieldtable = new PropertyFieldTable(); + } + + public JMSPropertyFieldTable(FieldTable table) + { + _fieldtable = table; + } + + public JMSPropertyFieldTable(ByteBuffer buffer, long length) throws JMSException + { + try + { + _fieldtable = new PropertyFieldTable(buffer, length); + } + catch (AMQFrameDecodingException e) + { + JMSException error = new JMSException(e.getMessage()); + error.setLinkedException(e); + throw error; + } + } + + private void checkPropertyName(String propertyName) + { + if (propertyName == null) + { + throw new IllegalArgumentException("Property name must not be null"); + } + else if ("".equals(propertyName)) + { + throw new IllegalArgumentException("Property name must not be the empty string"); + } + + checkIdentiferFormat(propertyName); + } + + protected static void checkIdentiferFormat(String propertyName) + { +// JMS requirements 3.5.1 Property Names +// Identifiers: +// - An identifier is an unlimited-length character sequence that must begin +// with a Java identifier start character; all following characters must be Java +// identifier part characters. An identifier start character is any character for +// which the method Character.isJavaIdentifierStart returns true. This includes +// '_' and '$'. An identifier part character is any character for which the +// method Character.isJavaIdentifierPart returns true. +// - Identifiers cannot be the names NULL, TRUE, or FALSE. +// – Identifiers cannot be NOT, AND, OR, BETWEEN, LIKE, IN, IS, or +// ESCAPE. +// – Identifiers are either header field references or property references. The +// type of a property value in a message selector corresponds to the type +// used to set the property. If a property that does not exist in a message is +// referenced, its value is NULL. The semantics of evaluating NULL values +// in a selector are described in Section 3.8.1.2, “Null Values.” +// – The conversions that apply to the get methods for properties do not +// apply when a property is used in a message selector expression. For +// example, suppose you set a property as a string value, as in the +// following: +// myMessage.setStringProperty("NumberOfOrders", "2"); +// The following expression in a message selector would evaluate to false, +// because a string cannot be used in an arithmetic expression: +// "NumberOfOrders > 1" +// – Identifiers are case sensitive. +// – Message header field references are restricted to JMSDeliveryMode, +// JMSPriority, JMSMessageID, JMSTimestamp, JMSCorrelationID, and +// JMSType. JMSMessageID, JMSCorrelationID, and JMSType values may be +// null and if so are treated as a NULL value. + + if (Boolean.getBoolean("strict-jms")) + { + // JMS start character + if (!(Character.isJavaIdentifierStart(propertyName.charAt(0)))) + { + throw new IllegalArgumentException("Identifier '" + propertyName + "' does not start with a valid JMS identifier start character"); + } + + // JMS part character + int length = propertyName.length(); + for (int c = 1; c < length; c++) + { + if (!(Character.isJavaIdentifierPart(propertyName.charAt(c)))) + { + throw new IllegalArgumentException("Identifier '" + propertyName + "' contains an invalid JMS identifier character"); + } + } + + // JMS invalid names + if ((propertyName.equals("NULL") + || propertyName.equals("TRUE") + || propertyName.equals("FALSE") + || propertyName.equals("NOT") + || propertyName.equals("AND") + || propertyName.equals("OR") + || propertyName.equals("BETWEEN") + || propertyName.equals("LIKE") + || propertyName.equals("IN") + || propertyName.equals("IS") + || propertyName.equals("ESCAPE"))) + { + throw new IllegalArgumentException("Identifier '" + propertyName + "' is not allowed in JMS"); + } + } + + } + + // MapMessage Interface + public boolean getBoolean(String string) throws JMSException + { + Boolean b = _fieldtable.getBoolean(string); + + if (b == null) + { + if (_fieldtable.containsKey(string)) + { + Object str = _fieldtable.getObject(string); + + if (str == null || !(str instanceof String)) + { + throw new MessageFormatException("getBoolean can't use " + string + " item."); + } + else + { + return Boolean.valueOf((String) str); + } + } + else + { + b = Boolean.valueOf(null); + } + } + + return b; + } + + public char getCharacter(String string) throws JMSException + { + Character c = _fieldtable.getCharacter(string); + + if (c == null) + { + if (_fieldtable.get(string) instanceof Character) + { + throw new NullPointerException("Cannot convert null char"); + } + else + { + throw new MessageFormatException("getChar can't use " + string + " item."); + } + } + else + { + return (char) c; + } + } + + public byte[] getBytes(String string) throws JMSException + { + byte[] bs = _fieldtable.getBytes(string); + + if (bs == null) + { + throw new MessageFormatException("getBytes can't use " + string + " item."); + } + else + { + return bs; + } + } + + public byte getByte(String string) throws JMSException + { + try + { + Byte b = _fieldtable.getByte(string); + if (b == null) + { + if (_fieldtable.containsKey(string)) + { + Object str = _fieldtable.getObject(string); + + if (str == null || !(str instanceof String)) + { + throw new MessageFormatException("getByte can't use " + string + " item."); + } + else + { + return Byte.valueOf((String) str); + } + } + else + { + b = Byte.valueOf(null); + } + } + + return b; + } + catch (NumberFormatException nfe) + { + throw new MessageFormatException(nfe.getMessage()); + } + } + + public short getShort(String string) throws JMSException + { + try + { + Short s = _fieldtable.getShort(string); + + if (s == null) + { + s = Short.valueOf(getByte(string)); + } + + return s; + } + catch (NumberFormatException nfe) + { + throw new MessageFormatException(nfe.getMessage()); + } + } + + public int getInteger(String string) throws JMSException + { + try + { + Integer i = _fieldtable.getInteger(string); + + if (i == null) + { + i = Integer.valueOf(getShort(string)); + } + + return i; + } + catch (NumberFormatException nfe) + { + throw new MessageFormatException(nfe.getMessage()); + } + } + + public long getLong(String string) throws JMSException + { + try + { + Long l = _fieldtable.getLong(string); + + if (l == null) + { + l = Long.valueOf(getInteger(string)); + } + + return l; + } + catch (NumberFormatException nfe) + { + throw new MessageFormatException(nfe.getMessage()); + } + + } + + public float getFloat(String string) throws JMSException + { + try + { + Float f = _fieldtable.getFloat(string); + + if (f == null) + { + if (_fieldtable.containsKey(string)) + { + Object str = _fieldtable.getObject(string); + + if (str == null || !(str instanceof String)) + { + throw new MessageFormatException("getFloat can't use " + string + " item."); + } + else + { + return Float.valueOf((String) str); + } + } + else + { + f = Float.valueOf(null); + } + + } + + return f; + } + catch (NumberFormatException nfe) + { + throw new MessageFormatException(nfe.getMessage()); + } + } + + public double getDouble(String string) throws JMSException + { + try + { + Double d = _fieldtable.getDouble(string); + + if (d == null) + { + d = Double.valueOf(getFloat(string)); + } + + return d; + } + catch (NumberFormatException nfe) + { + throw new MessageFormatException(nfe.getMessage()); + } + } + + public String getString(String string) throws JMSException + { + String s = _fieldtable.getString(string); + + if (s == null) + { + if (_fieldtable.containsKey(string)) + { + Object o = _fieldtable.getObject(string); + if (o instanceof byte[]) + { + throw new MessageFormatException("getObject couldn't find " + string + " item."); + } + else + { + if (o == null) + { + return null; + } + else + { + s = String.valueOf(o); + } + } + } + } + + return s; + } + + public Object getObject(String string) throws JMSException + { + return _fieldtable.getObject(string); + } + + public void setBoolean(String string, boolean b) throws JMSException + { + checkPropertyName(string); + _fieldtable.setBoolean(string, b); + } + + public void setChar(String string, char c) throws JMSException + { + checkPropertyName(string); + _fieldtable.setChar(string, c); + } + + public Object setBytes(String string, byte[] bytes) + { + return _fieldtable.setBytes(string, bytes, 0, bytes.length); + } + + public Object setBytes(String string, byte[] bytes, int start, int length) + { + return _fieldtable.setBytes(string, bytes, start, length); + } + + public void setByte(String string, byte b) throws JMSException + { + checkPropertyName(string); + _fieldtable.setByte(string, b); + } + + public void setShort(String string, short i) throws JMSException + { + checkPropertyName(string); + _fieldtable.setShort(string, i); + } + + public void setInteger(String string, int i) throws JMSException + { + checkPropertyName(string); + _fieldtable.setInteger(string, i); + } + + public void setLong(String string, long l) throws JMSException + { + checkPropertyName(string); + _fieldtable.setLong(string, l); + } + + public void setFloat(String string, float v) throws JMSException + { + checkPropertyName(string); + _fieldtable.setFloat(string, v); + } + + public void setDouble(String string, double v) throws JMSException + { + checkPropertyName(string); + _fieldtable.setDouble(string, v); + } + + public void setString(String string, String string1) throws JMSException + { + checkPropertyName(string); + _fieldtable.setString(string, string1); + } + + public void setObject(String string, Object object) throws JMSException + { + checkPropertyName(string); + try + { + _fieldtable.setObject(string, object); + } + catch (AMQPInvalidClassException aice) + { + throw new JMSException("Only primatives are allowed object is:" + object.getClass()); + } + } + + public boolean itemExists(String string) throws JMSException + { + return _fieldtable.containsKey(string); + } + + public void setFieldTable(FieldTable headers) + { + _fieldtable = headers; + } + + public Enumeration getPropertyNames() + { + return _fieldtable.getPropertyNames(); + } + + public void clear() + { + _fieldtable.clear(); + } + + public boolean propertyExists(String propertyName) + { + return _fieldtable.propertyExists(propertyName); + } + + public Object put(Object key, Object value) + { + return _fieldtable.put(key, value); + } + + public Object remove(String propertyName) + { + return _fieldtable.remove(propertyName); + } + + public boolean isEmpty() + { + return _fieldtable.isEmpty(); + } + + public void writeToBuffer(ByteBuffer data) + { + _fieldtable.writeToBuffer(data); + } + + public Enumeration getMapNames() + { + return getPropertyNames(); + } +} diff --git a/java/common/src/main/java/org/apache/qpid/framing/PropertyFieldTable.java b/java/common/src/main/java/org/apache/qpid/framing/PropertyFieldTable.java index 8c9b5f3b4c..df4ab1d21f 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/PropertyFieldTable.java +++ b/java/common/src/main/java/org/apache/qpid/framing/PropertyFieldTable.java @@ -22,6 +22,7 @@ package org.apache.qpid.framing; import org.apache.log4j.Logger; import org.apache.mina.common.ByteBuffer; +import org.apache.qpid.AMQPInvalidClassException; import java.util.Collection; import java.util.Enumeration; @@ -31,38 +32,13 @@ import java.util.Map; import java.util.Set; import java.util.StringTokenizer; import java.util.Vector; +import java.util.HashMap; //extends FieldTable public class PropertyFieldTable implements FieldTable { private static final Logger _logger = Logger.getLogger(PropertyFieldTable.class); - public static final char AMQP_DECIMAL_PROPERTY_PREFIX = 'D'; - public static final char AMQP_UNSIGNEDINT_PROPERTY_PREFIX = 'I'; - public static final char AMQP_TIMESTAMP_PROPERTY_PREFIX = 'T'; - public static final char AMQP_STRING_PROPERTY_PREFIX = 'S'; - public static final char AMQP_ASCII_CHARACTER_PROPERTY_PREFIX = 'k'; - public static final char AMQP_ASCII_STRING_PROPERTY_PREFIX = 'c'; - public static final char AMQP_WIDE_STRING_PROPERTY_PREFIX = 'C'; - public static final char AMQP_BINARY_PROPERTY_PREFIX = 'x'; - public static final char AMQP_NULL_STRING_PROPERTY_PREFIX = 'n'; - - public static final char BOOLEAN_PROPERTY_PREFIX = 't'; - public static final char BYTE_PROPERTY_PREFIX = 'b'; - public static final char SHORT_PROPERTY_PREFIX = 's'; - public static final char INT_PROPERTY_PREFIX = 'i'; - public static final char LONG_PROPERTY_PREFIX = 'l'; - public static final char FLOAT_PROPERTY_PREFIX = 'f'; - public static final char DOUBLE_PROPERTY_PREFIX = 'd'; - - public static final char NULL_STRING_PROPERTY_PREFIX = AMQP_NULL_STRING_PROPERTY_PREFIX; - public static final char STRING_PROPERTY_PREFIX = AMQP_STRING_PROPERTY_PREFIX; - public static final char CHAR_PROPERTY_PREFIX = AMQP_ASCII_CHARACTER_PROPERTY_PREFIX; - public static final char BYTES_PROPERTY_PREFIX = AMQP_BINARY_PROPERTY_PREFIX; - - //Our custom prefix for encoding across the wire - private static final char XML_PROPERTY_PREFIX = 'X'; - private static final String BOOLEAN = "boolean"; private static final String BYTE = "byte"; private static final String BYTES = "bytes"; @@ -72,6 +48,7 @@ public class PropertyFieldTable implements FieldTable private static final String FLOAT = "float"; private static final String DOUBLE = "double"; private static final String STRING = "string"; + private static final String NULL_STRING = "nullstring"; private static final String CHAR = "char"; private static final String UNKNOWN = "unknown type"; @@ -81,14 +58,58 @@ public class PropertyFieldTable implements FieldTable private static final String BYTES_OPEN_XML_START = "<" + BYTES; private LinkedHashMap<String, Object> _properties; - private LinkedHashMap<String, String> _propertyNamesTypeMap; - private long _encodedSize = 0;//EncodingUtils.unsignedIntegerLength(); + private LinkedHashMap<String, Prefix> _propertyNamesTypeMap; + private long _encodedSize = 0; + + public static enum Prefix + { + //AMQP FieldTable Wire Types + AMQP_DECIMAL_PROPERTY_PREFIX('D'), + AMQP_UNSIGNED_SHORT_PROPERTY_PREFIX('S'), + AMQP_UNSIGNED_INT_PROPERTY_PREFIX('I'), + AMQP_UNSIGNED_LONG_PROPERTY_PREFIX('L'), + AMQP_DOUBLE_EXTTENDED_PROPERTY_PREFIX('D'), + + AMQP_TIMESTAMP_PROPERTY_PREFIX('T'), + AMQP_BINARY_PROPERTY_PREFIX('x'), + + //Strings + AMQP_ASCII_STRING_PROPERTY_PREFIX('c'), + AMQP_WIDE_STRING_PROPERTY_PREFIX('C'), + AMQP_NULL_STRING_PROPERTY_PREFIX('n'), + + //Java Primative Types + AMQP_BOOLEAN_PROPERTY_PREFIX('t'), + AMQP_BYTE_PROPERTY_PREFIX('b'), + AMQP_ASCII_CHARACTER_PROPERTY_PREFIX('k'), + AMQP_SHORT_PROPERTY_PREFIX('s'), + AMQP_INT_PROPERTY_PREFIX('i'), + AMQP_LONG_PROPERTY_PREFIX('l'), + AMQP_FLOAT_PROPERTY_PREFIX('f'), + AMQP_DOUBLE_PROPERTY_PREFIX('d'); + + private final char _identifier; + + Prefix(char identifier) + { + _identifier = identifier; + _reverseTypeMap.put(identifier, this); + } + + public final char identifier() + { + return _identifier; + } + + } + + public static Map<Character, Prefix> _reverseTypeMap = new HashMap<Character, Prefix>(); public PropertyFieldTable() { super(); _properties = new LinkedHashMap<String, Object>(); - _propertyNamesTypeMap = new LinkedHashMap<String, String>(); + _propertyNamesTypeMap = new LinkedHashMap<String, Prefix>(); } public PropertyFieldTable(String textFormat) @@ -100,7 +121,8 @@ public class PropertyFieldTable implements FieldTable } catch (Exception e) { - _logger.error("Unable to decode PropertyFieldTable format:" + textFormat, e); + _logger.warn("Unable to decode PropertyFieldTable format:" + textFormat, e); + throw new IllegalArgumentException("Unable to decode PropertyFieldTable format:" + textFormat); } } @@ -118,17 +140,17 @@ public class PropertyFieldTable implements FieldTable } // ************ Getters - - private Object get(String propertyName, char prefix) + private Object get(String propertyName, Prefix prefix) { - String type = _propertyNamesTypeMap.get(propertyName); + //Retrieve the type associated with this name + Prefix type = _propertyNamesTypeMap.get(propertyName); if (type == null) { return null; } - if (type.equals("" + prefix)) + if (type.equals(prefix)) { return _properties.get(propertyName); } @@ -140,7 +162,7 @@ public class PropertyFieldTable implements FieldTable public Boolean getBoolean(String string) { - Object o = get(string, BOOLEAN_PROPERTY_PREFIX); + Object o = get(string, Prefix.AMQP_BOOLEAN_PROPERTY_PREFIX); if (o != null && o instanceof Boolean) { return (Boolean) o; @@ -153,7 +175,7 @@ public class PropertyFieldTable implements FieldTable public Byte getByte(String string) { - Object o = get(string, BYTE_PROPERTY_PREFIX); + Object o = get(string, Prefix.AMQP_BYTE_PROPERTY_PREFIX); if (o != null) { return (Byte) o; @@ -166,7 +188,7 @@ public class PropertyFieldTable implements FieldTable public Short getShort(String string) { - Object o = get(string, SHORT_PROPERTY_PREFIX); + Object o = get(string, Prefix.AMQP_SHORT_PROPERTY_PREFIX); if (o != null) { return (Short) o; @@ -179,7 +201,7 @@ public class PropertyFieldTable implements FieldTable public Integer getInteger(String string) { - Object o = get(string, INT_PROPERTY_PREFIX); + Object o = get(string, Prefix.AMQP_INT_PROPERTY_PREFIX); if (o != null) { return (Integer) o; @@ -192,7 +214,7 @@ public class PropertyFieldTable implements FieldTable public Long getLong(String string) { - Object o = get(string, LONG_PROPERTY_PREFIX); + Object o = get(string, Prefix.AMQP_LONG_PROPERTY_PREFIX); if (o != null) { return (Long) o; @@ -205,20 +227,20 @@ public class PropertyFieldTable implements FieldTable public Float getFloat(String string) { - Object o = get(string, FLOAT_PROPERTY_PREFIX); + Object o = get(string, Prefix.AMQP_FLOAT_PROPERTY_PREFIX); if (o != null) { return (Float) o; } else { - return null; //Float.valueOf(null); ??? + return null; } } public Double getDouble(String string) { - Object o = get(string, DOUBLE_PROPERTY_PREFIX); + Object o = get(string, Prefix.AMQP_DOUBLE_PROPERTY_PREFIX); if (o != null) { return (Double) o; @@ -231,50 +253,55 @@ public class PropertyFieldTable implements FieldTable public String getString(String string) { - Object o = get(string, STRING_PROPERTY_PREFIX); + Object o = get(string, Prefix.AMQP_ASCII_STRING_PROPERTY_PREFIX); if (o != null) { return (String) o; } else { - - - String type = _propertyNamesTypeMap.get(string); - - if (type == null || type.equals("" + NULL_STRING_PROPERTY_PREFIX)) + o = get(string, Prefix.AMQP_WIDE_STRING_PROPERTY_PREFIX); + if (o != null) { - return null; + return (String) o; } else { - char itype = type.charAt(0); - Object value = _properties.get(string); + Prefix type = _propertyNamesTypeMap.get(string); - switch (itype) + if (type == null || type.equals(Prefix.AMQP_NULL_STRING_PROPERTY_PREFIX)) { - case STRING_PROPERTY_PREFIX: - case BYTES_PROPERTY_PREFIX: - return null; - default: - case BYTE_PROPERTY_PREFIX: - case BOOLEAN_PROPERTY_PREFIX: - case SHORT_PROPERTY_PREFIX: - case INT_PROPERTY_PREFIX: - case LONG_PROPERTY_PREFIX: - case FLOAT_PROPERTY_PREFIX: - case DOUBLE_PROPERTY_PREFIX: - return String.valueOf(value); - case CHAR_PROPERTY_PREFIX: - if (value == null) - { - throw new NullPointerException("null char cannot be converted to String"); - } - else - { - return String.valueOf(value); - } + return null; + } + else + { + switch (type) + { + case AMQP_ASCII_STRING_PROPERTY_PREFIX: + case AMQP_WIDE_STRING_PROPERTY_PREFIX: + case AMQP_BINARY_PROPERTY_PREFIX: + return null; + default: + case AMQP_BYTE_PROPERTY_PREFIX: + case AMQP_BOOLEAN_PROPERTY_PREFIX: + case AMQP_SHORT_PROPERTY_PREFIX: + case AMQP_INT_PROPERTY_PREFIX: + case AMQP_LONG_PROPERTY_PREFIX: + case AMQP_FLOAT_PROPERTY_PREFIX: + case AMQP_DOUBLE_PROPERTY_PREFIX: + return String.valueOf(_properties.get(string)); + case AMQP_ASCII_CHARACTER_PROPERTY_PREFIX: + Object value = _properties.get(string); + if (value == null) + { + throw new NullPointerException("null char cannot be converted to String"); + } + else + { + return String.valueOf(value); + } + } } } } @@ -282,7 +309,7 @@ public class PropertyFieldTable implements FieldTable public Character getCharacter(String string) { - Object o = get(string, CHAR_PROPERTY_PREFIX); + Object o = get(string, Prefix.AMQP_ASCII_CHARACTER_PROPERTY_PREFIX); if (o != null) { return (Character) o; @@ -295,7 +322,7 @@ public class PropertyFieldTable implements FieldTable public byte[] getBytes(String string) { - Object o = get(string, BYTES_PROPERTY_PREFIX); + Object o = get(string, Prefix.AMQP_BINARY_PROPERTY_PREFIX); if (o != null) { return (byte[]) o; @@ -315,54 +342,62 @@ public class PropertyFieldTable implements FieldTable public Object setBoolean(String string, boolean b) { - return put(BOOLEAN_PROPERTY_PREFIX + string, b); + return put(Prefix.AMQP_BOOLEAN_PROPERTY_PREFIX, string, b); } public Object setByte(String string, byte b) { - return put(BYTE_PROPERTY_PREFIX + string, b); + return put(Prefix.AMQP_BYTE_PROPERTY_PREFIX, string, b); } public Object setShort(String string, short i) { - return put(SHORT_PROPERTY_PREFIX + string, i); + return put(Prefix.AMQP_SHORT_PROPERTY_PREFIX, string, i); } public Object setInteger(String string, int i) { - return put(INT_PROPERTY_PREFIX + string, i); + return put(Prefix.AMQP_INT_PROPERTY_PREFIX, string, i); } public Object setLong(String string, long l) { - return put(LONG_PROPERTY_PREFIX + string, l); + return put(Prefix.AMQP_LONG_PROPERTY_PREFIX, string, l); } public Object setFloat(String string, float v) { - return put(FLOAT_PROPERTY_PREFIX + string, v); + return put(Prefix.AMQP_FLOAT_PROPERTY_PREFIX, string, v); } public Object setDouble(String string, double v) { - return put(DOUBLE_PROPERTY_PREFIX + string, v); + return put(Prefix.AMQP_DOUBLE_PROPERTY_PREFIX, string, v); } public Object setString(String string, String string1) { if (string1 == null) { - return put(NULL_STRING_PROPERTY_PREFIX + string, null); + return put(Prefix.AMQP_NULL_STRING_PROPERTY_PREFIX, string, null); } else { - return put(STRING_PROPERTY_PREFIX + string, string1); + //FIXME: determine string encoding and set either WIDE or ASCII string +// if () + { + return put(Prefix.AMQP_WIDE_STRING_PROPERTY_PREFIX, string, string1); + } +// else +// { +// return put(Prefix.AMQP_ASCII_STRING_PROPERTY_PREFIX, string, string1); +// } } } public Object setChar(String string, char c) { - return put(CHAR_PROPERTY_PREFIX + string, c); + return put(Prefix.AMQP_ASCII_CHARACTER_PROPERTY_PREFIX, string, c); } public Object setBytes(String string, byte[] bytes) @@ -372,7 +407,7 @@ public class PropertyFieldTable implements FieldTable public Object setBytes(String string, byte[] bytes, int start, int length) { - return put(BYTES_PROPERTY_PREFIX + string, sizeByteArray(bytes, start, length)); + return put(Prefix.AMQP_BINARY_PROPERTY_PREFIX, string, sizeByteArray(bytes, start, length)); } private byte[] sizeByteArray(byte[] bytes, int start, int length) @@ -458,7 +493,7 @@ public class PropertyFieldTable implements FieldTable } } } - return null; + throw new AMQPInvalidClassException("Only Primatives objects allowed Object is:" + object.getClass()); } // ***** Methods @@ -481,23 +516,12 @@ public class PropertyFieldTable implements FieldTable public boolean propertyExists(String propertyName) { - return _propertyNamesTypeMap.containsKey(propertyName); + return itemExists(propertyName); } public boolean itemExists(String string) { - Iterator keys = _properties.keySet().iterator(); - - while (keys.hasNext()) - { - String key = (String) keys.next(); - - if (key.endsWith(string)) - { - return true; - } - } - return false; + return _properties.containsKey(string); } public String toString() @@ -515,16 +539,9 @@ public class PropertyFieldTable implements FieldTable { final Map.Entry entry = (Map.Entry) it.next(); final String propertyName = (String) entry.getKey(); - if (propertyName == null) - { - buf.append("\nInternal error: Property with NULL key defined"); - } - else - { - buf.append('\n'); - buf.append(valueAsXML(table._propertyNamesTypeMap.get(propertyName) + propertyName, entry.getValue())); - } + buf.append('\n'); + buf.append(valueAsXML(table._propertyNamesTypeMap.get(propertyName), propertyName, entry.getValue())); } buf.append("\n"); buf.append(PROPERTY_FIELD_TABLE_CLOSE_XML); @@ -532,18 +549,14 @@ public class PropertyFieldTable implements FieldTable return buf.toString(); } - private static String valueAsXML(String name, Object value) + private static String valueAsXML(Prefix type, String propertyName, Object value) { - char propertyPrefix = name.charAt(0); - String propertyName = name.substring(1); - - StringBuffer buf = new StringBuffer(); // Start Tag - buf.append(propertyXML(name, true)); + buf.append(propertyXML(type, propertyName, true)); // Value - if (propertyPrefix == BYTES_PROPERTY_PREFIX) + if (type.equals(Prefix.AMQP_BINARY_PROPERTY_PREFIX)) { //remove '>' buf.deleteCharAt(buf.length() - 1); @@ -555,22 +568,19 @@ public class PropertyFieldTable implements FieldTable } else { - buf.append(String.valueOf(value)); + if (!type.equals(Prefix.AMQP_NULL_STRING_PROPERTY_PREFIX)) + { + buf.append(String.valueOf(value)); + } } - //End Tag - buf.append(propertyXML(name, false)); + buf.append(propertyXML(type, propertyName, false)); return buf.toString(); } - private Object checkPropertyName(String name) + private void checkPropertyName(String propertyName) { - String propertyName = name.substring(1); - char propertyPrefix = name.charAt(0); - - Object previous = null; - if (propertyName == null) { throw new IllegalArgumentException("Property name must not be null"); @@ -581,34 +591,11 @@ public class PropertyFieldTable implements FieldTable } checkIdentiferFormat(propertyName); - - String currentValue = _propertyNamesTypeMap.get(propertyName); - - if (currentValue != null) - { - previous = _properties.remove(currentValue + propertyName); - - // If we are in effect deleting the value (see comment on null values being deleted - // below) then we also need to remove the name from the encoding length. - if (previous == null) - { - _encodedSize -= EncodingUtils.encodedShortStringLength(propertyName); - } - - // FIXME: Should be able to short-cut this process if the old and new values are - // the same object and/or type and size... - _encodedSize -= getEncodingSize(currentValue + propertyName, previous) + 1; - } - - _propertyNamesTypeMap.put(propertyName, "" + propertyPrefix); - - return previous; } protected static void checkIdentiferFormat(String propertyName) { - // AMQP Spec: 4.2.5.5 Field Tables // Guidelines for implementers: // * Field names MUST start with a letter, '$' or '#' and may continue with @@ -619,96 +606,23 @@ public class PropertyFieldTable implements FieldTable // 503 (syntax error). Conformance test: amq_wlp_table_01. // * A peer MUST handle duplicate fields by using only the first instance. -// JMS requirements 3.5.1 Property Names -// Identifiers: -// - An identifier is an unlimited-length character sequence that must begin -// with a Java identifier start character; all following characters must be Java -// identifier part characters. An identifier start character is any character for -// which the method Character.isJavaIdentifierStart returns true. This includes -// '_' and '$'. An identifier part character is any character for which the -// method Character.isJavaIdentifierPart returns true. -// - Identifiers cannot be the names NULL, TRUE, or FALSE. -// – Identifiers cannot be NOT, AND, OR, BETWEEN, LIKE, IN, IS, or -// ESCAPE. -// – Identifiers are either header field references or property references. The -// type of a property value in a message selector corresponds to the type -// used to set the property. If a property that does not exist in a message is -// referenced, its value is NULL. The semantics of evaluating NULL values -// in a selector are described in Section 3.8.1.2, “Null Values.” -// – The conversions that apply to the get methods for properties do not -// apply when a property is used in a message selector expression. For -// example, suppose you set a property as a string value, as in the -// following: -// myMessage.setStringProperty("NumberOfOrders", "2"); -// The following expression in a message selector would evaluate to false, -// because a string cannot be used in an arithmetic expression: -// "NumberOfOrders > 1" -// – Identifiers are case sensitive. -// – Message header field references are restricted to JMSDeliveryMode, -// JMSPriority, JMSMessageID, JMSTimestamp, JMSCorrelationID, and -// JMSType. JMSMessageID, JMSCorrelationID, and JMSType values may be -// null and if so are treated as a NULL value. - - - if (Boolean.getBoolean("strict-jms")) - { - // JMS start character - if (!(Character.isJavaIdentifierStart(propertyName.charAt(0)))) - { - throw new IllegalArgumentException("Identifier '" + propertyName + "' does not start with a valid JMS identifier start character"); - } - - // JMS part character - int length = propertyName.length(); - for (int c = 1; c < length; c++) - { - if (!(Character.isJavaIdentifierPart(propertyName.charAt(c)))) - { - throw new IllegalArgumentException("Identifier '" + propertyName + "' contains an invalid JMS identifier character"); - } - } - - // JMS invalid names - if (!(propertyName.equals("NULL") - || propertyName.equals("TRUE") - || propertyName.equals("FALSE") - || propertyName.equals("NOT") - || propertyName.equals("AND") - || propertyName.equals("OR") - || propertyName.equals("BETWEEN") - || propertyName.equals("LIKE") - || propertyName.equals("IN") - || propertyName.equals("IS") - || propertyName.equals("ESCAPE"))) - { - throw new IllegalArgumentException("Identifier '" + propertyName + "' is not allowed in JMS"); - } - - } - else + // AMQP length limit + if (propertyName.length() > 128) { - // AMQP length limit - if (propertyName.length() > 128) - { - throw new IllegalArgumentException("AMQP limits property names to 128 characters"); - } - - // AMQ start character - if (!(Character.isLetter(propertyName.charAt(0)) - || propertyName.charAt(0) == '$' - || propertyName.charAt(0) == '#')) - { - throw new IllegalArgumentException("Identifier '" + propertyName + "' does not start with a valid AMQP start character"); - } + throw new IllegalArgumentException("AMQP limits property names to 128 characters"); } + // AMQ start character + if (!(Character.isLetter(propertyName.charAt(0)) + || propertyName.charAt(0) == '$' + || propertyName.charAt(0) == '#')) + { + throw new IllegalArgumentException("Identifier '" + propertyName + "' does not start with a valid AMQP start character"); + } } - private static String propertyXML(String name, boolean start) + private static String propertyXML(Prefix type, String propertyName, boolean start) { - char propertyPrefix = name.charAt(0); - String propertyName = name.substring(1); - StringBuffer buf = new StringBuffer(); if (start) @@ -720,40 +634,44 @@ public class PropertyFieldTable implements FieldTable buf.append("</"); } - switch (propertyPrefix) + switch (type) { - case BOOLEAN_PROPERTY_PREFIX: + case AMQP_BOOLEAN_PROPERTY_PREFIX: buf.append(BOOLEAN); break; - case BYTE_PROPERTY_PREFIX: + case AMQP_BYTE_PROPERTY_PREFIX: buf.append(BYTE); break; - case BYTES_PROPERTY_PREFIX: + case AMQP_BINARY_PROPERTY_PREFIX: buf.append(BYTES); break; - case SHORT_PROPERTY_PREFIX: + case AMQP_SHORT_PROPERTY_PREFIX: buf.append(SHORT); break; - case INT_PROPERTY_PREFIX: + case AMQP_INT_PROPERTY_PREFIX: buf.append(INT); break; - case LONG_PROPERTY_PREFIX: + case AMQP_LONG_PROPERTY_PREFIX: buf.append(LONG); break; - case FLOAT_PROPERTY_PREFIX: + case AMQP_FLOAT_PROPERTY_PREFIX: buf.append(FLOAT); break; - case DOUBLE_PROPERTY_PREFIX: + case AMQP_DOUBLE_PROPERTY_PREFIX: buf.append(DOUBLE); break; - case STRING_PROPERTY_PREFIX: + case AMQP_NULL_STRING_PROPERTY_PREFIX: + buf.append(NULL_STRING); + break; + case AMQP_ASCII_STRING_PROPERTY_PREFIX: + case AMQP_WIDE_STRING_PROPERTY_PREFIX: buf.append(STRING); break; - case CHAR_PROPERTY_PREFIX: + case AMQP_ASCII_CHARACTER_PROPERTY_PREFIX: buf.append(CHAR); break; default: - buf.append(UNKNOWN + " (identifier ").append(propertyPrefix).append(")"); + buf.append(UNKNOWN + " (identifier ").append(type.identifier()).append(")"); break; } @@ -774,9 +692,9 @@ public class PropertyFieldTable implements FieldTable for (int index = 0; index < bytes.length; index++) { buf.append("\n"); - buf.append(propertyXML(BYTE_PROPERTY_PREFIX + propertyName + "[" + index + "]", true)); + buf.append(propertyXML(Prefix.AMQP_BYTE_PROPERTY_PREFIX, propertyName + "[" + index + "]", true)); buf.append(bytes[index]); - buf.append(propertyXML(BYTE_PROPERTY_PREFIX + propertyName + "[" + index + "]", false)); + buf.append(propertyXML(Prefix.AMQP_BYTE_PROPERTY_PREFIX, propertyName + "[" + index + "]", false)); } buf.append("\n"); return buf.toString(); @@ -800,16 +718,26 @@ public class PropertyFieldTable implements FieldTable { StringTokenizer tokenizer = new StringTokenizer(textFormat, "\n"); + boolean finished = false; boolean processing = false; boolean processing_bytes = false; + if (!tokenizer.hasMoreTokens()) + { + throw new IllegalArgumentException("XML has no tokens to parse."); + } + while (tokenizer.hasMoreTokens()) { String token = tokenizer.nextToken(); - if (token.equals(PROPERTY_FIELD_TABLE_CLOSE_XML) - || token.equals(BYTES_CLOSE_XML)) + if (token.equals(PROPERTY_FIELD_TABLE_CLOSE_XML)) + { + processing = false; + finished = true; + } + if (token.equals(BYTES_CLOSE_XML)) { processing = false; } @@ -840,6 +768,12 @@ public class PropertyFieldTable implements FieldTable processing = true; } } + + if (!finished) + { + throw new IllegalArgumentException("XML was not in a valid format."); + } + } private void processXMLLine(String xmlline) @@ -887,6 +821,7 @@ public class PropertyFieldTable implements FieldTable int byteStart = xmlline.indexOf('<', headerEnd); + //Don't think this is required. if (byteStart > 0) { while (!xmlline.startsWith(BYTES_CLOSE_XML, byteStart)) @@ -924,8 +859,12 @@ public class PropertyFieldTable implements FieldTable { setDouble(propertyName, Double.parseDouble(value)); } - if (type.equals(STRING)) + if (type.equals(STRING) || type.equals(NULL_STRING)) { + if (type.equals(NULL_STRING)) + { + value = null; + } setString(propertyName, value); } if (type.equals(CHAR)) @@ -934,7 +873,7 @@ public class PropertyFieldTable implements FieldTable } if (type.equals(UNKNOWN)) { - _logger.error("Ignoring unknown property value:" + xmlline); + _logger.warn("Ignoring unknown property value:" + xmlline); } } @@ -942,16 +881,14 @@ public class PropertyFieldTable implements FieldTable public void writeToBuffer(ByteBuffer buffer) { - final boolean debug = _logger.isDebugEnabled(); + final boolean trace = _logger.isTraceEnabled(); - if (debug) + if (trace) { - _logger.debug("FieldTable::writeToBuffer: Writing encoded size of " + _encodedSize + "..."); + _logger.trace("FieldTable::writeToBuffer: Writing encoded size of " + _encodedSize + "..."); } EncodingUtils.writeUnsignedInteger(buffer, _encodedSize); - //EncodingUtils.writeLong(buffer, _encodedSize); - putDataInBuffer(buffer); } @@ -1001,43 +938,39 @@ public class PropertyFieldTable implements FieldTable return setObject(key.toString(), value); } - protected Object put(String key, Object value) + protected Object put(Prefix type, String propertyName, Object value) { - Object previous = checkPropertyName(key); + checkPropertyName(propertyName); + //remove the previous value + Object previous = remove(propertyName); - String propertyName = key.substring(1); - char propertyPrefix = _propertyNamesTypeMap.get(propertyName).charAt(0); - if (_logger.isDebugEnabled()) + if (_logger.isTraceEnabled()) { - _logger.debug("Put:" + propertyName + - " encoding Now:" + _encodedSize + + int valueSize = 0; + if (value != null) + { + valueSize = getEncodingSize(type, value); + } + _logger.trace("Put:" + propertyName + + " encoding size Now:" + _encodedSize + " name size= " + EncodingUtils.encodedShortStringLength(propertyName) + - " value size= " + getEncodingSize(key, value)); + " value size= " + valueSize); } - // This prevents the item from being sent. - // JMS needs these propertyNames for lookups. - //if (value != null) - { - //Add the size of the propertyName - _encodedSize += EncodingUtils.encodedShortStringLength(propertyName); + //Add the size of the propertyName plus one for the type identifier + _encodedSize += EncodingUtils.encodedShortStringLength(propertyName) + 1; - // For now: Setting a null value is the equivalent of deleting it. - // This is ambiguous in the JMS spec and needs thrashing out and potentially - // testing against other implementations. - - //Add the size of the content plus one for the type identifier - _encodedSize += getEncodingSize(key, value) + 1; - } - - if (_logger.isDebugEnabled()) + if (value != null) { - _logger.debug("Put: new encodingSize " + _encodedSize); + //Add the size of the content + _encodedSize += getEncodingSize(type, value); } - _properties.put((String) propertyName, value); + //Store new values + _propertyNamesTypeMap.put(propertyName, type); + _properties.put(propertyName, value); return previous; } @@ -1047,14 +980,14 @@ public class PropertyFieldTable implements FieldTable if (_properties.containsKey(key)) { final Object value = _properties.remove(key); - String typePrefix = _propertyNamesTypeMap.remove(key); + Prefix type = _propertyNamesTypeMap.remove(key); // plus one for the type _encodedSize -= EncodingUtils.encodedShortStringLength(((String) key)) + 1; // This check is, for now, unnecessary (we don't store null values). if (value != null) { - _encodedSize -= getEncodingSize(typePrefix, value); + _encodedSize -= getEncodingSize(type, value); } return value; } @@ -1077,6 +1010,7 @@ public class PropertyFieldTable implements FieldTable public void clear() { + _encodedSize = 0; _properties.clear(); _propertyNamesTypeMap.clear(); } @@ -1113,93 +1047,82 @@ public class PropertyFieldTable implements FieldTable while (it.hasNext()) { - Map.Entry me = (Map.Entry) it.next(); String propertyName = (String) me.getKey(); //The type value - char propertyPrefix = _propertyNamesTypeMap.get(propertyName).charAt(0); + Prefix type = _propertyNamesTypeMap.get(propertyName); Object value = me.getValue(); try { - - if (_logger.isDebugEnabled()) + if (_logger.isTraceEnabled()) { - _logger.debug("Writing Property:" + propertyName + - " Type:" + propertyPrefix + + _logger.trace("Writing Property:" + propertyName + + " Type:" + type + " Value:" + value); - _logger.debug("Buffer Position:" + buffer.position() + + _logger.trace("Buffer Position:" + buffer.position() + " Remaining:" + buffer.remaining()); } - //The actual param name skipping type + //Write the actual parameter name EncodingUtils.writeShortStringBytes(buffer, propertyName); - - switch (propertyPrefix) + switch (type) { - - case BOOLEAN_PROPERTY_PREFIX: - buffer.put((byte) BOOLEAN_PROPERTY_PREFIX); + case AMQP_BOOLEAN_PROPERTY_PREFIX: + buffer.put((byte) Prefix.AMQP_BOOLEAN_PROPERTY_PREFIX.identifier()); EncodingUtils.writeBoolean(buffer, (Boolean) value); break; - case BYTE_PROPERTY_PREFIX: - buffer.put((byte) BYTE_PROPERTY_PREFIX); + case AMQP_BYTE_PROPERTY_PREFIX: + buffer.put((byte) Prefix.AMQP_BYTE_PROPERTY_PREFIX.identifier()); EncodingUtils.writeByte(buffer, (Byte) value); break; - case SHORT_PROPERTY_PREFIX: - buffer.put((byte) SHORT_PROPERTY_PREFIX); + case AMQP_SHORT_PROPERTY_PREFIX: + buffer.put((byte) Prefix.AMQP_SHORT_PROPERTY_PREFIX.identifier()); EncodingUtils.writeShort(buffer, (Short) value); break; - case INT_PROPERTY_PREFIX: - buffer.put((byte) INT_PROPERTY_PREFIX); + case AMQP_INT_PROPERTY_PREFIX: + buffer.put((byte) Prefix.AMQP_INT_PROPERTY_PREFIX.identifier()); EncodingUtils.writeInteger(buffer, (Integer) value); break; - case AMQP_UNSIGNEDINT_PROPERTY_PREFIX: // Currently we don't create these - buffer.put((byte) AMQP_UNSIGNEDINT_PROPERTY_PREFIX); + case AMQP_UNSIGNED_INT_PROPERTY_PREFIX: // Currently we don't create these + buffer.put((byte) Prefix.AMQP_UNSIGNED_INT_PROPERTY_PREFIX.identifier()); EncodingUtils.writeUnsignedInteger(buffer, (Long) value); break; - case LONG_PROPERTY_PREFIX: - buffer.put((byte) LONG_PROPERTY_PREFIX); + case AMQP_LONG_PROPERTY_PREFIX: + buffer.put((byte) Prefix.AMQP_LONG_PROPERTY_PREFIX.identifier()); EncodingUtils.writeLong(buffer, (Long) value); break; - case FLOAT_PROPERTY_PREFIX: - buffer.put((byte) FLOAT_PROPERTY_PREFIX); + case AMQP_FLOAT_PROPERTY_PREFIX: + buffer.put((byte) Prefix.AMQP_FLOAT_PROPERTY_PREFIX.identifier()); EncodingUtils.writeFloat(buffer, (Float) value); break; - case DOUBLE_PROPERTY_PREFIX: - buffer.put((byte) DOUBLE_PROPERTY_PREFIX); + case AMQP_DOUBLE_PROPERTY_PREFIX: + buffer.put((byte) Prefix.AMQP_DOUBLE_PROPERTY_PREFIX.identifier()); EncodingUtils.writeDouble(buffer, (Double) value); break; - case NULL_STRING_PROPERTY_PREFIX: - buffer.put((byte) NULL_STRING_PROPERTY_PREFIX); + case AMQP_NULL_STRING_PROPERTY_PREFIX: + buffer.put((byte) Prefix.AMQP_NULL_STRING_PROPERTY_PREFIX.identifier()); break; - case AMQP_WIDE_STRING_PROPERTY_PREFIX: - // TODO: look at using proper charset encoder - buffer.put((byte) STRING_PROPERTY_PREFIX); + buffer.put((byte) Prefix.AMQP_WIDE_STRING_PROPERTY_PREFIX.identifier()); + // FIXME: use proper charset encoder EncodingUtils.writeLongStringBytes(buffer, (String) value); break; case AMQP_ASCII_STRING_PROPERTY_PREFIX: - case STRING_PROPERTY_PREFIX: // AMQP_STRING_PROPERTY_PREFIX: //This is a simple ASCII string - buffer.put((byte) STRING_PROPERTY_PREFIX); + buffer.put((byte) Prefix.AMQP_ASCII_STRING_PROPERTY_PREFIX.identifier()); EncodingUtils.writeLongStringBytes(buffer, (String) value); break; - case CHAR_PROPERTY_PREFIX: - buffer.put((byte) CHAR_PROPERTY_PREFIX); + case AMQP_ASCII_CHARACTER_PROPERTY_PREFIX: + buffer.put((byte) Prefix.AMQP_ASCII_CHARACTER_PROPERTY_PREFIX.identifier()); EncodingUtils.writeChar(buffer, (Character) value); break; - case BYTES_PROPERTY_PREFIX: - buffer.put((byte) BYTES_PROPERTY_PREFIX); + case AMQP_BINARY_PROPERTY_PREFIX: + buffer.put((byte) Prefix.AMQP_BINARY_PROPERTY_PREFIX.identifier()); EncodingUtils.writeBytes(buffer, (byte[]) value); break; - case XML_PROPERTY_PREFIX: - // Encode as XML - buffer.put((byte) XML_PROPERTY_PREFIX); - EncodingUtils.writeLongStringBytes(buffer, valueAsXML(propertyPrefix + propertyName, value)); - break; default: { // Should never get here @@ -1209,172 +1132,152 @@ public class PropertyFieldTable implements FieldTable } catch (Exception e) { - if (_logger.isDebugEnabled()) + if (_logger.isTraceEnabled()) { - _logger.debug("Exception thrown:" + e); - _logger.debug("Writing Property:" + propertyName + - " Type:" + propertyPrefix + + _logger.trace("Exception thrown:" + e); + _logger.trace("Writing Property:" + propertyName + + " Type:" + type + " Value:" + value); - _logger.debug("Buffer Position:" + buffer.position() + + _logger.trace("Buffer Position:" + buffer.position() + " Remaining:" + buffer.remaining()); } throw new RuntimeException(e); } } - } public void setFromBuffer(ByteBuffer buffer, long length) throws AMQFrameDecodingException { - final boolean debug = _logger.isDebugEnabled(); + final boolean trace = _logger.isTraceEnabled(); int sizeRead = 0; while (sizeRead < length) { int sizeRemaining = buffer.remaining(); final String key = EncodingUtils.readShortString(buffer); - // TODO: use proper charset decoder + byte iType = buffer.get(); - final char type = (char) iType; - Object value = null; + + Prefix type = _reverseTypeMap.get((char) iType); + + Object value; switch (type) { - case BOOLEAN_PROPERTY_PREFIX: + case AMQP_BOOLEAN_PROPERTY_PREFIX: value = EncodingUtils.readBoolean(buffer); break; - case BYTE_PROPERTY_PREFIX: + case AMQP_BYTE_PROPERTY_PREFIX: value = EncodingUtils.readByte(buffer); break; - case SHORT_PROPERTY_PREFIX: + case AMQP_SHORT_PROPERTY_PREFIX: value = EncodingUtils.readShort(buffer); break; - case INT_PROPERTY_PREFIX: + case AMQP_INT_PROPERTY_PREFIX: value = EncodingUtils.readInteger(buffer); break; - case AMQP_UNSIGNEDINT_PROPERTY_PREFIX:// This will only fit in a long - case LONG_PROPERTY_PREFIX: + case AMQP_UNSIGNED_INT_PROPERTY_PREFIX:// This will only fit in a long + //Change this type for java lookups + type = Prefix.AMQP_LONG_PROPERTY_PREFIX; + case AMQP_LONG_PROPERTY_PREFIX: value = EncodingUtils.readLong(buffer); break; - case FLOAT_PROPERTY_PREFIX: + case AMQP_FLOAT_PROPERTY_PREFIX: value = EncodingUtils.readFloat(buffer); break; - case DOUBLE_PROPERTY_PREFIX: + case AMQP_DOUBLE_PROPERTY_PREFIX: value = EncodingUtils.readDouble(buffer); break; - - // TODO: use proper charset decoder case AMQP_WIDE_STRING_PROPERTY_PREFIX: + // FIXME: use proper charset encoder case AMQP_ASCII_STRING_PROPERTY_PREFIX: - case STRING_PROPERTY_PREFIX: // AMQP_STRING_PROPERTY_PREFIX: value = EncodingUtils.readLongString(buffer); break; - case NULL_STRING_PROPERTY_PREFIX: + case AMQP_NULL_STRING_PROPERTY_PREFIX: value = null; break; - case CHAR_PROPERTY_PREFIX: + case AMQP_ASCII_CHARACTER_PROPERTY_PREFIX: value = EncodingUtils.readChar((buffer)); break; - case BYTES_PROPERTY_PREFIX: + case AMQP_BINARY_PROPERTY_PREFIX: value = EncodingUtils.readBytes(buffer); break; - case XML_PROPERTY_PREFIX: - processXMLLine(EncodingUtils.readLongString(buffer)); - break; default: String msg = "Field '" + key + "' - unsupported field table type: " + type + "."; - //some extra debug information... + //some extra trace information... msg += " (" + iType + "), length=" + length + ", sizeRead=" + sizeRead + ", sizeRemaining=" + sizeRemaining; throw new AMQFrameDecodingException(msg); } sizeRead += (sizeRemaining - buffer.remaining()); - if (debug) + if (trace) { - _logger.debug("FieldTable::PropFieldTable(buffer," + length + "): Read type '" + type + "', key '" + key + "', value '" + value + "' (now read " + sizeRead + " of " + length + " encoded bytes)..."); + _logger.trace("FieldTable::PropFieldTable(buffer," + length + "): Read type '" + type + "', key '" + key + "', value '" + value + "' (now read " + sizeRead + " of " + length + " encoded bytes)..."); } - if (type != XML_PROPERTY_PREFIX) - { - setObject(key, value); - if (value == null) - { - _logger.debug("setFromBuffer: value is null for key:" + key); - _propertyNamesTypeMap.put(key, "" + type); - _properties.put(key, null); - } - } + put(type, key, value); } - if (debug) + if (trace) { - _logger.debug("FieldTable::FieldTable(buffer," + length + "): Done."); + _logger.trace("FieldTable::FieldTable(buffer," + length + "): Done."); } } - /** - * @param name the property name with type prefix + * @param type the type to calucluate encoding for * @param value the property value * @return integer */ - private static int getEncodingSize(String name, Object value) + private static int getEncodingSize(Prefix type, Object value) { int encodingSize = 0; - char propertyPrefix = name.charAt(0); - - switch (propertyPrefix) + switch (type) { - case BOOLEAN_PROPERTY_PREFIX: - encodingSize += EncodingUtils.encodedBooleanLength(); + case AMQP_BOOLEAN_PROPERTY_PREFIX: + encodingSize = EncodingUtils.encodedBooleanLength(); break; - case BYTE_PROPERTY_PREFIX: - encodingSize += EncodingUtils.encodedByteLength(); + case AMQP_BYTE_PROPERTY_PREFIX: + encodingSize = EncodingUtils.encodedByteLength(); break; - case SHORT_PROPERTY_PREFIX: - encodingSize += EncodingUtils.encodedShortLength(); + case AMQP_SHORT_PROPERTY_PREFIX: + encodingSize = EncodingUtils.encodedShortLength(); break; - case INT_PROPERTY_PREFIX: - encodingSize += EncodingUtils.encodedIntegerLength(); + case AMQP_INT_PROPERTY_PREFIX: + encodingSize = EncodingUtils.encodedIntegerLength(); break; - case LONG_PROPERTY_PREFIX: - encodingSize += EncodingUtils.encodedLongLength(); + case AMQP_LONG_PROPERTY_PREFIX: + encodingSize = EncodingUtils.encodedLongLength(); break; - case FLOAT_PROPERTY_PREFIX: - encodingSize += EncodingUtils.encodedFloatLength(); + case AMQP_FLOAT_PROPERTY_PREFIX: + encodingSize = EncodingUtils.encodedFloatLength(); break; - case DOUBLE_PROPERTY_PREFIX: - encodingSize += EncodingUtils.encodedDoubleLength(); + case AMQP_DOUBLE_PROPERTY_PREFIX: + encodingSize = EncodingUtils.encodedDoubleLength(); break; case AMQP_WIDE_STRING_PROPERTY_PREFIX: + // FIXME: use proper charset encoder case AMQP_ASCII_STRING_PROPERTY_PREFIX: - case STRING_PROPERTY_PREFIX: //AMQP_STRING_PROPERTY_PREFIX: - encodingSize += EncodingUtils.encodedLongStringLength((String) value); + encodingSize = EncodingUtils.encodedLongStringLength((String) value); break; - case NULL_STRING_PROPERTY_PREFIX: - // There is no need for additional size beyond the prefix +// This is not required as this method is never called if the value is null +// case AMQP_NULL_STRING_PROPERTY_PREFIX: +// // There is no need for additional size beyond the prefix +// break; + case AMQP_ASCII_CHARACTER_PROPERTY_PREFIX: + encodingSize = EncodingUtils.encodedCharLength(); break; - case CHAR_PROPERTY_PREFIX: - encodingSize += EncodingUtils.encodedCharLength(); - break; - case BYTES_PROPERTY_PREFIX: - encodingSize += 1 + ((byte[]) value).length; - break; - case XML_PROPERTY_PREFIX: - encodingSize += EncodingUtils.encodedLongStringLength(valueAsXML(name, value)); + case AMQP_BINARY_PROPERTY_PREFIX: + encodingSize = 1 + ((byte[]) value).length; break; default: - //encodingSize = 1 + EncodingUtils.encodedLongstrLength(String.valueOf(value)); - // We are using XML String encoding throw new IllegalArgumentException("Unsupported type in field table: " + value.getClass()); } -// the extra byte for the type indicator is calculated in the name + // the extra byte for the type indicator is calculated in the name return encodingSize; } - - } diff --git a/java/common/src/main/java/org/apache/qpid/pool/Event.java b/java/common/src/main/java/org/apache/qpid/pool/Event.java index 71ab6e7863..7364b9293a 100644 --- a/java/common/src/main/java/org/apache/qpid/pool/Event.java +++ b/java/common/src/main/java/org/apache/qpid/pool/Event.java @@ -109,6 +109,6 @@ class Event public String toString() { - return "Event: type " + type + ", data: " + data; + return "Event: type " + type + ", data: " + data; } } diff --git a/java/common/src/test/java/org/apache/qpid/framing/JMSPropertyFieldTableTest.java b/java/common/src/test/java/org/apache/qpid/framing/JMSPropertyFieldTableTest.java new file mode 100644 index 0000000000..98202ddd1a --- /dev/null +++ b/java/common/src/test/java/org/apache/qpid/framing/JMSPropertyFieldTableTest.java @@ -0,0 +1,1020 @@ +/* + * 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.qpid.framing; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import java.util.Enumeration; +import java.util.Iterator; +import java.util.Map; +import java.util.HashMap; + +import org.apache.mina.common.ByteBuffer; +import org.apache.log4j.Logger; + +import javax.jms.JMSException; +import javax.jms.MessageFormatException; + +public class JMSPropertyFieldTableTest extends TestCase +{ + + private static final Logger _logger = Logger.getLogger(JMSPropertyFieldTableTest.class); + + + public void setUp() + { + System.getProperties().setProperty("strict-jms", "true"); + } + + public void tearDown() + { + System.getProperties().remove("strict-jms"); + } + + /** + * Test that setting a similar named value replaces any previous value set on that name + */ + public void testReplacement() throws JMSException + { + JMSPropertyFieldTable table1 = new JMSPropertyFieldTable(); + //Set a boolean value + table1.setBoolean("value", true); + + // reset value to an integer + table1.setInteger("value", Integer.MAX_VALUE); + + //Check boolean value is null + try + { + table1.getBoolean("value"); + } + catch (MessageFormatException mfe) + { + //normal execution + } + // ... and integer value is good + Assert.assertEquals(Integer.MAX_VALUE, table1.getInteger("value")); + } + + public void testRemoval() throws JMSException + { + JMSPropertyFieldTable table1 = new JMSPropertyFieldTable(); + //Set a boolean value + table1.setBoolean("value", true); + + Assert.assertTrue(table1.getBoolean("value")); + + table1.remove("value"); + + //Check boolean value is null + try + { + table1.getBoolean("value"); + } + catch (MessageFormatException mfe) + { + //normal execution + } + } + + + /** + * Set a boolean and check that we can only get it back as a boolean and a string + * Check that attempting to lookup a non existent value returns null + */ + public void testBoolean() throws JMSException + { + JMSPropertyFieldTable table1 = new JMSPropertyFieldTable(); + table1.setBoolean("value", true); + Assert.assertTrue(table1.propertyExists("value")); + + //Test Getting right value back + Assert.assertEquals(true, table1.getBoolean("value")); + + //Check we don't get anything back for other gets + try + { + table1.getByte("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + + try + { + table1.getByte("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + + try + { + table1.getShort("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + + try + { + table1.getDouble("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + + try + { + table1.getFloat("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + + try + { + table1.getInteger("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + + try + { + table1.getLong("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + + //except value as a string + Assert.assertEquals("true", table1.getString("value")); + + table1.remove("value"); + //but after a remove it doesn't + Assert.assertFalse(table1.propertyExists("value")); + + // Table should now have zero size for encoding + checkEmpty(table1); + + //Looking up an invalid value will return false + Assert.assertFalse(table1.getBoolean("Rubbish")); + } + + /** + * Set a byte and check that we can only get it back as a byte and a string + * Check that attempting to lookup a non existent value returns null + */ + public void testByte() throws JMSException + { + JMSPropertyFieldTable table1 = new JMSPropertyFieldTable(); + table1.setByte("value", Byte.MAX_VALUE); + Assert.assertTrue(table1.propertyExists("value")); + + //Tets lookups we shouldn't get anything back for other gets + //we should get right value back for this type .... + try + { + table1.getBoolean("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + + try + { + table1.getDouble("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + try + { + table1.getFloat("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + + Assert.assertEquals(Byte.MAX_VALUE, (byte) table1.getShort("value")); + Assert.assertEquals(Byte.MAX_VALUE, (byte) table1.getInteger("value")); + Assert.assertEquals(Byte.MAX_VALUE, (byte) table1.getLong("value")); + Assert.assertEquals(Byte.MAX_VALUE, table1.getByte("value")); + //... and a the string value of it. + Assert.assertEquals("" + Byte.MAX_VALUE, table1.getString("value")); + + table1.remove("value"); + //but after a remove it doesn't + Assert.assertFalse(table1.propertyExists("value")); + + // Table should now have zero size for encoding + checkEmpty(table1); + + //Looking up an invalid value returns null + try + { + table1.getByte("Rubbish"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + + } + + + /** + * Set a short and check that we can only get it back as a short and a string + * Check that attempting to lookup a non existent value returns null + */ + public void testShort() throws JMSException + { + JMSPropertyFieldTable table1 = new JMSPropertyFieldTable(); + table1.setShort("value", Short.MAX_VALUE); + Assert.assertTrue(table1.propertyExists("value")); + + //Tets lookups we shouldn't get anything back for other gets + //we should get right value back for this type .... + + try + { + table1.getBoolean("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + try + { + table1.getByte("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + + try + { + table1.getDouble("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + try + { + table1.getFloat("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + + + Assert.assertEquals(Short.MAX_VALUE, (short) table1.getLong("value")); + Assert.assertEquals(Short.MAX_VALUE, (short) table1.getInteger("value")); + Assert.assertEquals(Short.MAX_VALUE, table1.getShort("value")); + + //... and a the string value of it. + Assert.assertEquals("" + Short.MAX_VALUE, table1.getString("value")); + + table1.remove("value"); + //but after a remove it doesn't + Assert.assertFalse(table1.propertyExists("value")); + + // Table should now have zero size for encoding + checkEmpty(table1); + + //Looking up an invalid value returns null + try + { + table1.getShort("Rubbish"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfe) + { + //normal path + } + } + + + /** + * Set a double and check that we can only get it back as a double + * Check that attempting to lookup a non existent value returns null + */ + public void testDouble() throws JMSException + { + JMSPropertyFieldTable table1 = new JMSPropertyFieldTable(); + table1.setDouble("value", Double.MAX_VALUE); + Assert.assertTrue(table1.propertyExists("value")); + + //Tets lookups we shouldn't get anything back for other gets + //we should get right value back for this type .... + try + { + table1.getBoolean("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + try + { + table1.getByte("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + try + { + table1.getShort("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + try + { + table1.getFloat("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + try + { + table1.getInteger("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + try + { + table1.getLong("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + + Assert.assertEquals(Double.MAX_VALUE, table1.getDouble("value")); + //... and a the string value of it. + Assert.assertEquals("" + Double.MAX_VALUE, table1.getString("value")); + + table1.remove("value"); + //but after a remove it doesn't + Assert.assertFalse(table1.propertyExists("value")); + + // Table should now have zero size for encoding + checkEmpty(table1); + + //Looking up an invalid value returns null + try + { + table1.getDouble("Rubbish"); + fail("Should throw NullPointerException as float.valueOf will try sunreadJavaFormatString"); + } + catch (NullPointerException mfe) + { + //normal path + } + + } + + + /** + * Set a float and check that we can only get it back as a float + * Check that attempting to lookup a non existent value returns null + */ + public void testFloat() throws JMSException + { + JMSPropertyFieldTable table1 = new JMSPropertyFieldTable(); + table1.setFloat("value", Float.MAX_VALUE); + Assert.assertTrue(table1.propertyExists("value")); + + //Tets lookups we shouldn't get anything back for other gets + //we should get right value back for this type .... + try + { + table1.getBoolean("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + try + { + table1.getByte("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + try + { + table1.getShort("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + try + { + table1.getInteger("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + try + { + table1.getLong("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + + + Assert.assertEquals(Float.MAX_VALUE, table1.getFloat("value")); + Assert.assertEquals(Float.MAX_VALUE, (float) table1.getDouble("value")); + + //... and a the string value of it. + Assert.assertEquals("" + Float.MAX_VALUE, table1.getString("value")); + + table1.remove("value"); + //but after a remove it doesn't + Assert.assertFalse(table1.propertyExists("value")); + + // Table should now have zero size for encoding + checkEmpty(table1); + + //Looking up an invalid value returns null + try + { + table1.getFloat("Rubbish"); + fail("Should throw NullPointerException as float.valueOf will try sunreadJavaFormatString"); + } + catch (NullPointerException mfe) + { + //normal path + } + } + + + /** + * Set an int and check that we can only get it back as an int + * Check that attempting to lookup a non existent value returns null + */ + public void testInt() throws JMSException + { + JMSPropertyFieldTable table1 = new JMSPropertyFieldTable(); + table1.setInteger("value", Integer.MAX_VALUE); + Assert.assertTrue(table1.propertyExists("value")); + + //Tets lookups we shouldn't get anything back for other gets + //we should get right value back for this type .... + try + { + table1.getBoolean("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + try + { + table1.getByte("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + try + { + table1.getShort("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + try + { + table1.getDouble("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + try + { + table1.getFloat("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + + + Assert.assertEquals(Integer.MAX_VALUE, table1.getLong("value")); + + Assert.assertEquals(Integer.MAX_VALUE, table1.getInteger("value")); + + //... and a the string value of it. + Assert.assertEquals("" + Integer.MAX_VALUE, table1.getString("value")); + + table1.remove("value"); + //but after a remove it doesn't + Assert.assertFalse(table1.propertyExists("value")); + + // Table should now have zero size for encoding + checkEmpty(table1); + + //Looking up an invalid value returns null + try + { + table1.getInteger("Rubbish"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfe) + { + //normal path + } + } + + + /** + * Set a long and check that we can only get it back as a long + * Check that attempting to lookup a non existent value returns null + */ + public void testLong() throws JMSException + { + JMSPropertyFieldTable table1 = new JMSPropertyFieldTable(); + table1.setLong("value", Long.MAX_VALUE); + Assert.assertTrue(table1.propertyExists("value")); + + //Tets lookups we shouldn't get anything back for other gets + //we should get right value back for this type .... + try + { + table1.getBoolean("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + try + { + table1.getByte("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + try + { + table1.getShort("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + try + { + table1.getDouble("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + try + { + table1.getFloat("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + try + { + table1.getInteger("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + + + Assert.assertEquals(Long.MAX_VALUE, table1.getLong("value")); + + //... and a the string value of it. + Assert.assertEquals("" + Long.MAX_VALUE, table1.getString("value")); + + table1.remove("value"); + //but after a remove it doesn't + Assert.assertFalse(table1.propertyExists("value")); + + // Table should now have zero size for encoding + checkEmpty(table1); + + //Looking up an invalid value + try + { + table1.getLong("Rubbish"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException mfs) + { + //normal Execution + } + + } + + + /** + * Calls all methods that can be used to check the table is empty + * - getEncodedSize + * - isEmpty + * - size + * + * @param table to check is empty + */ + private void checkEmpty(JMSPropertyFieldTable table) + { + Assert.assertFalse(table.getPropertyNames().hasMoreElements()); + } + + + /** + * Set a String and check that we can only get it back as a String + * Check that attempting to lookup a non existent value returns null + */ + public void testString() throws JMSException + { + JMSPropertyFieldTable table1 = new JMSPropertyFieldTable(); + table1.setString("value", "Hello"); + Assert.assertTrue(table1.propertyExists("value")); + + //Tets lookups we shouldn't get anything back for other gets + //we should get right value back for this type .... + Assert.assertEquals(false, table1.getBoolean("value")); + + try + { + table1.getByte("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException nfs) + { + //normal Execution + } + try + { + table1.getShort("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException nfs) + { + //normal Execution + } + try + { + table1.getDouble("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException nfs) + { + //normal Execution + } + try + { + table1.getFloat("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException nfs) + { + //normal Execution + } + try + { + table1.getInteger("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException nfs) + { + //normal Execution + } + try + { + table1.getLong("value"); + fail("Should throw MessageFormatException"); + } + catch (MessageFormatException nfs) + { + //normal Execution + } + + Assert.assertEquals("Hello", table1.getString("value")); + + table1.remove("value"); + //but after a remove it doesn't + Assert.assertFalse(table1.propertyExists("value")); + + checkEmpty(table1); + + //Looking up an invalid value returns null + Assert.assertEquals(null, table1.getString("Rubbish")); + + //Additional Test that haven't been covered for string + table1.setObject("value", "Hello"); + //Check that it was set correctly + Assert.assertEquals("Hello", table1.getString("value")); + } + + + public void testValues() throws JMSException + { + JMSPropertyFieldTable table = new JMSPropertyFieldTable(); + table.setBoolean("bool", true); + table.setDouble("double", Double.MAX_VALUE); + table.setFloat("float", Float.MAX_VALUE); + table.setInteger("int", Integer.MAX_VALUE); + table.setLong("long", Long.MAX_VALUE); + table.setShort("short", Short.MAX_VALUE); + table.setString("string", "Hello"); + table.setString("nullstring", null); + + table.setObject("objectbool", true); + table.setObject("objectdouble", Double.MAX_VALUE); + table.setObject("objectfloat", Float.MAX_VALUE); + table.setObject("objectint", Integer.MAX_VALUE); + table.setObject("objectlong", Long.MAX_VALUE); + table.setObject("objectshort", Short.MAX_VALUE); + table.setObject("objectstring", "Hello"); + + + Assert.assertEquals(true, table.getBoolean("bool")); + + Assert.assertEquals(Double.MAX_VALUE, table.getDouble("double")); + Assert.assertEquals(Float.MAX_VALUE, table.getFloat("float")); + Assert.assertEquals(Integer.MAX_VALUE, table.getInteger("int")); + Assert.assertEquals(Long.MAX_VALUE, table.getLong("long")); + Assert.assertEquals(Short.MAX_VALUE, table.getShort("short")); + Assert.assertEquals("Hello", table.getString("string")); + Assert.assertEquals(null, table.getString("null-string")); + + Assert.assertEquals(true, table.getObject("objectbool")); + Assert.assertEquals(Double.MAX_VALUE, table.getObject("objectdouble")); + Assert.assertEquals(Float.MAX_VALUE, table.getObject("objectfloat")); + Assert.assertEquals(Integer.MAX_VALUE, table.getObject("objectint")); + Assert.assertEquals(Long.MAX_VALUE, table.getObject("objectlong")); + Assert.assertEquals(Short.MAX_VALUE, table.getObject("objectshort")); + Assert.assertEquals("Hello", table.getObject("objectstring")); + } + + /** + * Additional test checkPropertyName doesn't accept Null + */ + public void testCheckPropertyNameasNull() throws JMSException + { + JMSPropertyFieldTable table = new JMSPropertyFieldTable(); + + try + { + table.setObject(null, "String"); + fail("Null property name is not allowed"); + } + catch (IllegalArgumentException iae) + { + //normal path + } + checkEmpty(table); + } + + + /** + * Additional test checkPropertyName doesn't accept an empty String + */ + public void testCheckPropertyNameasEmptyString() throws JMSException + { + JMSPropertyFieldTable table = new JMSPropertyFieldTable(); + + try + { + table.setObject("", "String"); + fail("empty property name is not allowed"); + } + catch (IllegalArgumentException iae) + { + //normal path + } + checkEmpty(table); + } + + + /** + * Additional test checkPropertyName doesn't accept an empty String + */ + public void testCheckPropertyNamehasMaxLength() throws JMSException + { + JMSPropertyFieldTable table = new JMSPropertyFieldTable(); + + StringBuffer longPropertyName = new StringBuffer(129); + + for (int i = 0; i < 129; i++) + { + longPropertyName.append("x"); + } + + try + { + table.setObject(longPropertyName.toString(), "String"); + fail("property name must be < 128 characters"); + } + catch (IllegalArgumentException iae) + { + _logger.warn("JMS requires infinite property names AMQP limits us to 128 characters"); + } + + checkEmpty(table); + } + + + /** + * Additional test checkPropertyName starts with a letter + */ + public void testCheckPropertyNameStartCharacterIsLetter() throws JMSException + { + JMSPropertyFieldTable table = new JMSPropertyFieldTable(); + + //Try a name that starts with a number + try + { + table.setObject("1", "String"); + fail("property name must start with a letter"); + } + catch (IllegalArgumentException iae) + { + //normal path + } + + checkEmpty(table); + } + + /** + * Additional test checkPropertyName starts with a letter + */ + public void testCheckPropertyNameContainsInvalidCharacter() throws JMSException + { + JMSPropertyFieldTable table = new JMSPropertyFieldTable(); + + //Try a name that starts with a number + try + { + table.setObject("hello there", "String"); + fail("property name cannot contain spaces"); + } + catch (IllegalArgumentException iae) + { + //normal path + } + + checkEmpty(table); + } + + + /** + * Additional test checkPropertyName starts with a letter + */ + public void testCheckPropertyNameIsInvalid() throws JMSException + { + JMSPropertyFieldTable table = new JMSPropertyFieldTable(); + + //Try a name that starts with a number + try + { + table.setObject("ESCAPE", "String"); + fail("property name must not contains spaces"); + } + catch (IllegalArgumentException iae) + { + //normal path + } + + checkEmpty(table); + } + + /** + * Additional test checkPropertyName starts with a hash or a dollar + */ + public void testCheckPropertyNameStartCharacterIsHashorDollar() throws JMSException + { + _logger.warn("Test:testCheckPropertyNameStartCharacterIsHashorDollar will fail JMS compilance as # and $ are not valid in a jms identifier"); +// JMSPropertyFieldTable table = new JMSPropertyFieldTable(); +// +// //Try a name that starts with a number +// try +// { +// table.setObject("#", "String"); +// table.setObject("$", "String"); +// } +// catch (IllegalArgumentException iae) +// { +// fail("property name are allowed to start with # and $s in AMQP"); +// } + } + + /** + * Test the contents of the sets + */ + public void testSets() + { + + JMSPropertyFieldTable table = new JMSPropertyFieldTable(); + + table.put("n1", "1"); + table.put("n2", "2"); + table.put("n3", "3"); + + Enumeration enumerator = table.getPropertyNames(); + Assert.assertEquals("n1", enumerator.nextElement()); + Assert.assertEquals("n2", enumerator.nextElement()); + Assert.assertEquals("n3", enumerator.nextElement()); + Assert.assertFalse(enumerator.hasMoreElements()); + } + + public static junit.framework.Test suite() + { + return new junit.framework.TestSuite(JMSPropertyFieldTableTest.class); + } + +} diff --git a/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java b/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java index f2067a5649..5256c62054 100644 --- a/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java +++ b/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java @@ -24,14 +24,22 @@ import junit.framework.Assert; import junit.framework.TestCase; import java.util.Enumeration; +import java.util.Iterator; +import java.util.Map; +import java.util.HashMap; import org.apache.mina.common.ByteBuffer; +import org.apache.log4j.Logger; +import org.apache.qpid.AMQPInvalidClassException; public class PropertyFieldTableTest extends TestCase { - //Test byte modification + private static final Logger _logger = Logger.getLogger(PropertyFieldTableTest.class); + /** + * Test that modifying a byte[] after setting property doesn't change property + */ public void testByteModification() { PropertyFieldTable table = new PropertyFieldTable(); @@ -46,197 +54,518 @@ public class PropertyFieldTableTest extends TestCase assertBytesNotEqual(bytes, table.getBytes("bytes")); } - //Test replacement - + /** + * Test that setting a similar named value replaces any previous value set on that name + */ public void testReplacement() { PropertyFieldTable table1 = new PropertyFieldTable(); + //Set a boolean value table1.setBoolean("value", true); + //Check size of table is correct (<Value length> + <type> + <Boolean length>) + int size = EncodingUtils.encodedShortStringLength("value") + 1 + EncodingUtils.encodedBooleanLength(); + Assert.assertEquals(size, table1.getEncodedSize()); + + // reset value to an integer table1.setInteger("value", Integer.MAX_VALUE); + + // Check the size has changed accordingly (<Value length> + <type> + <Integer length>) + size = EncodingUtils.encodedShortStringLength("value") + 1 + EncodingUtils.encodedIntegerLength(); + Assert.assertEquals(size, table1.getEncodedSize()); + + //Check boolean value is null Assert.assertEquals(null, table1.getBoolean("value")); + // ... and integer value is good Assert.assertEquals((Integer) Integer.MAX_VALUE, table1.getInteger("value")); } - //Test Lookups - public void testBooleanLookup() + /** + * Set a boolean and check that we can only get it back as a boolean and a string + * Check that attempting to lookup a non existent value returns null + */ + public void testBoolean() { PropertyFieldTable table1 = new PropertyFieldTable(); table1.setBoolean("value", true); + Assert.assertTrue(table1.propertyExists("value")); + //Test Getting right value back Assert.assertEquals((Boolean) true, table1.getBoolean("value")); - //Looking up an invalid value returns null - Assert.assertTrue(table1.getBoolean("Rubbish") == null); - - //Try reading value as a string + //Check we don't get anything back for other gets + Assert.assertEquals(null, table1.getByte("value")); + Assert.assertEquals(null, table1.getByte("value")); + Assert.assertEquals(null, table1.getShort("value")); + Assert.assertEquals(null, table1.getCharacter("value")); + Assert.assertEquals(null, table1.getDouble("value")); + Assert.assertEquals(null, table1.getFloat("value")); + Assert.assertEquals(null, table1.getInteger("value")); + Assert.assertEquals(null, table1.getLong("value")); + Assert.assertEquals(null, table1.getBytes("value")); + + //except value as a string Assert.assertEquals("true", table1.getString("value")); + + //Try setting a null value and read it back + table1.put(PropertyFieldTable.Prefix.AMQP_BOOLEAN_PROPERTY_PREFIX, "value", null); + + // Should be able to get the null back + Assert.assertEquals(null, table1.getBoolean("value")); + //but still contains the value + Assert.assertTrue(table1.containsKey("value")); + + table1.remove("value"); + //but after a remove it doesn't + Assert.assertFalse(table1.containsKey("value")); + + // Table should now have zero size for encoding + checkEmpty(table1); + + //Looking up an invalid value returns null + Assert.assertEquals(null, table1.getBoolean("Rubbish")); } - public void testByteLookup() + /** + * Set a byte and check that we can only get it back as a byte and a string + * Check that attempting to lookup a non existent value returns null + */ + public void testByte() { PropertyFieldTable table1 = new PropertyFieldTable(); - table1.setByte("value", (byte) 1); - Assert.assertEquals((Byte) (byte) 1, table1.getByte("value")); + table1.setByte("value", Byte.MAX_VALUE); + Assert.assertTrue(table1.propertyExists("value")); - //Looking up an invalid value returns null - Assert.assertTrue(table1.getByte("Rubbish") == null); + //Tets lookups we shouldn't get anything back for other gets + //we should get right value back for this type .... + Assert.assertEquals(null, table1.getBoolean("value")); + Assert.assertEquals(Byte.MAX_VALUE, (byte) table1.getByte("value")); + Assert.assertEquals(null, table1.getShort("value")); + Assert.assertEquals(null, table1.getCharacter("value")); + Assert.assertEquals(null, table1.getDouble("value")); + Assert.assertEquals(null, table1.getFloat("value")); + Assert.assertEquals(null, table1.getInteger("value")); + Assert.assertEquals(null, table1.getLong("value")); + Assert.assertEquals(null, table1.getBytes("value")); + + //... and a the string value of it. + Assert.assertEquals("" + Byte.MAX_VALUE, table1.getString("value")); + + //Try setting a null value and read it back + table1.put(PropertyFieldTable.Prefix.AMQP_BYTE_PROPERTY_PREFIX, "value", null); + + // Should be able to get the null back + Assert.assertEquals(null, table1.getByte("value")); - //Try reading value as a string - Assert.assertEquals("1", table1.getString("value")); + //but still contains the value + Assert.assertTrue(table1.containsKey("value")); + + table1.remove("value"); + //but after a remove it doesn't + Assert.assertFalse(table1.containsKey("value")); + + // Table should now have zero size for encoding + checkEmpty(table1); + + //Looking up an invalid value returns null + Assert.assertEquals(null, table1.getByte("Rubbish")); } - public void testShortLookup() + /** + * Set a short and check that we can only get it back as a short and a string + * Check that attempting to lookup a non existent value returns null + */ + public void testShort() { PropertyFieldTable table1 = new PropertyFieldTable(); table1.setShort("value", Short.MAX_VALUE); - Assert.assertEquals((Short) Short.MAX_VALUE, table1.getShort("value")); + Assert.assertTrue(table1.propertyExists("value")); - //Looking up an invalid value returns null - Assert.assertTrue(table1.getShort("Rubbish") == null); - - //Try reading value as a string + //Tets lookups we shouldn't get anything back for other gets + //we should get right value back for this type .... + Assert.assertEquals(null, table1.getBoolean("value")); + Assert.assertEquals(null, table1.getByte("value")); + Assert.assertEquals(Short.MAX_VALUE, (short) table1.getShort("value")); + Assert.assertEquals(null, table1.getCharacter("value")); + Assert.assertEquals(null, table1.getDouble("value")); + Assert.assertEquals(null, table1.getFloat("value")); + Assert.assertEquals(null, table1.getInteger("value")); + Assert.assertEquals(null, table1.getLong("value")); + Assert.assertEquals(null, table1.getBytes("value")); + + //... and a the string value of it. Assert.assertEquals("" + Short.MAX_VALUE, table1.getString("value")); + + //Try setting a null value and read it back + table1.put(PropertyFieldTable.Prefix.AMQP_SHORT_PROPERTY_PREFIX, "value", null); + + // Should be able to get the null back + Assert.assertEquals(null, table1.getShort("value")); + + //but still contains the value + Assert.assertTrue(table1.containsKey("value")); + + table1.remove("value"); + //but after a remove it doesn't + Assert.assertFalse(table1.containsKey("value")); + + // Table should now have zero size for encoding + checkEmpty(table1); + + //Looking up an invalid value returns null + Assert.assertEquals(null, table1.getShort("Rubbish")); } - public void testCharLookup() + /** + * Set a char and check that we can only get it back as a char + * Check that attempting to lookup a non existent value returns null + */ + public void testChar() { PropertyFieldTable table1 = new PropertyFieldTable(); - table1.setChar("value", 'b'); - Assert.assertEquals((Character) 'b', table1.getCharacter("value")); + table1.setChar("value", 'c'); + Assert.assertTrue(table1.propertyExists("value")); - //Looking up an invalid value returns null - Assert.assertTrue(table1.getCharacter("Rubbish") == null); + //Tets lookups we shouldn't get anything back for other gets + //we should get right value back for this type .... + Assert.assertEquals(null, table1.getBoolean("value")); + Assert.assertEquals(null, table1.getByte("value")); + Assert.assertEquals(null, table1.getShort("value")); + Assert.assertEquals('c', (char) table1.getCharacter("value")); + Assert.assertEquals(null, table1.getDouble("value")); + Assert.assertEquals(null, table1.getFloat("value")); + Assert.assertEquals(null, table1.getInteger("value")); + Assert.assertEquals(null, table1.getLong("value")); + Assert.assertEquals(null, table1.getBytes("value")); + + //... and a the string value of it. + Assert.assertEquals("c", table1.getString("value")); + + //Try setting a null value and read it back + table1.put(PropertyFieldTable.Prefix.AMQP_ASCII_CHARACTER_PROPERTY_PREFIX, "value", null); + + try + { + table1.getString("value"); + fail("Should throw NullPointerException"); + } + catch (NullPointerException npe) + { + //Normal Path + } + //but still contains the value + Assert.assertTrue(table1.containsKey("value")); + + table1.remove("value"); + //but after a remove it doesn't + Assert.assertFalse(table1.containsKey("value")); + + // Table should now have zero size for encoding + checkEmpty(table1); - //Try reading value as a string - Assert.assertEquals("b", table1.getString("value")); + //Looking up an invalid value returns null + Assert.assertEquals(null, table1.getCharacter("Rubbish")); } - public void testDoubleLookup() + + /** + * Set a double and check that we can only get it back as a double + * Check that attempting to lookup a non existent value returns null + */ + public void testDouble() { PropertyFieldTable table1 = new PropertyFieldTable(); table1.setDouble("value", Double.MAX_VALUE); - Assert.assertEquals(Double.MAX_VALUE, table1.getDouble("value")); - - //Looking up an invalid value returns null - Assert.assertTrue(table1.getDouble("Rubbish") == null); + Assert.assertTrue(table1.propertyExists("value")); - //Try reading value as a string + //Tets lookups we shouldn't get anything back for other gets + //we should get right value back for this type .... + Assert.assertEquals(null, table1.getBoolean("value")); + Assert.assertEquals(null, table1.getByte("value")); + Assert.assertEquals(null, table1.getShort("value")); + Assert.assertEquals(null, table1.getCharacter("value")); + Assert.assertEquals(Double.MAX_VALUE, (double) table1.getDouble("value")); + Assert.assertEquals(null, table1.getFloat("value")); + Assert.assertEquals(null, table1.getInteger("value")); + Assert.assertEquals(null, table1.getLong("value")); + Assert.assertEquals(null, table1.getBytes("value")); + + //... and a the string value of it. Assert.assertEquals("" + Double.MAX_VALUE, table1.getString("value")); + //Try setting a null value and read it back + table1.put(PropertyFieldTable.Prefix.AMQP_DOUBLE_PROPERTY_PREFIX, "value", null); + + Assert.assertEquals(null, table1.getDouble("value")); + + //but still contains the value + Assert.assertTrue(table1.containsKey("value")); + + table1.remove("value"); + //but after a remove it doesn't + Assert.assertFalse(table1.containsKey("value")); + + // Table should now have zero size for encoding + checkEmpty(table1); + + //Looking up an invalid value returns null + Assert.assertEquals(null, table1.getDouble("Rubbish")); } - public void testFloatLookup() + + /** + * Set a float and check that we can only get it back as a float + * Check that attempting to lookup a non existent value returns null + */ + public void testFloat() { PropertyFieldTable table1 = new PropertyFieldTable(); table1.setFloat("value", Float.MAX_VALUE); - Assert.assertEquals(Float.MAX_VALUE, table1.getFloat("value")); + Assert.assertTrue(table1.propertyExists("value")); - //Looking up an invalid value returns null - Assert.assertTrue(table1.getFloat("Rubbish") == null); - - //Try reading value as a string + //Tets lookups we shouldn't get anything back for other gets + //we should get right value back for this type .... + Assert.assertEquals(null, table1.getBoolean("value")); + Assert.assertEquals(null, table1.getByte("value")); + Assert.assertEquals(null, table1.getShort("value")); + Assert.assertEquals(null, table1.getCharacter("value")); + Assert.assertEquals(null, table1.getDouble("value")); + Assert.assertEquals(Float.MAX_VALUE, (float) table1.getFloat("value")); + Assert.assertEquals(null, table1.getInteger("value")); + Assert.assertEquals(null, table1.getLong("value")); + Assert.assertEquals(null, table1.getBytes("value")); + + //... and a the string value of it. Assert.assertEquals("" + Float.MAX_VALUE, table1.getString("value")); + //Try setting a null value and read it back + table1.put(PropertyFieldTable.Prefix.AMQP_FLOAT_PROPERTY_PREFIX, "value", null); + + Assert.assertEquals(null, table1.getFloat("value")); + + //but still contains the value + Assert.assertTrue(table1.containsKey("value")); + + table1.remove("value"); + //but after a remove it doesn't + Assert.assertFalse(table1.containsKey("value")); + + // Table should now have zero size for encoding + checkEmpty(table1); + + //Looking up an invalid value returns null + Assert.assertEquals(null, table1.getFloat("Rubbish")); } - public void testIntLookup() + + /** + * Set an int and check that we can only get it back as an int + * Check that attempting to lookup a non existent value returns null + */ + public void testInt() { PropertyFieldTable table1 = new PropertyFieldTable(); table1.setInteger("value", Integer.MAX_VALUE); - Assert.assertEquals((Integer) Integer.MAX_VALUE, table1.getInteger("value")); + Assert.assertTrue(table1.propertyExists("value")); - //Looking up an invalid value returns null - Assert.assertTrue(table1.getInteger("Rubbish") == null); - - //Try reading value as a string + //Tets lookups we shouldn't get anything back for other gets + //we should get right value back for this type .... + Assert.assertEquals(null, table1.getBoolean("value")); + Assert.assertEquals(null, table1.getByte("value")); + Assert.assertEquals(null, table1.getShort("value")); + Assert.assertEquals(null, table1.getCharacter("value")); + Assert.assertEquals(null, table1.getDouble("value")); + Assert.assertEquals(null, table1.getFloat("value")); + Assert.assertEquals(Integer.MAX_VALUE, (int) table1.getInteger("value")); + Assert.assertEquals(null, table1.getLong("value")); + Assert.assertEquals(null, table1.getBytes("value")); + + //... and a the string value of it. Assert.assertEquals("" + Integer.MAX_VALUE, table1.getString("value")); + //Try setting a null value and read it back + table1.put(PropertyFieldTable.Prefix.AMQP_INT_PROPERTY_PREFIX, "value", null); + + Assert.assertEquals(null, table1.getInteger("value")); + + //but still contains the value + Assert.assertTrue(table1.containsKey("value")); + + table1.remove("value"); + //but after a remove it doesn't + Assert.assertFalse(table1.containsKey("value")); + + // Table should now have zero size for encoding + checkEmpty(table1); + + //Looking up an invalid value returns null + Assert.assertEquals(null, table1.getInteger("Rubbish")); } - public void testLongLookup() + + /** + * Set a long and check that we can only get it back as a long + * Check that attempting to lookup a non existent value returns null + */ + public void testLong() { PropertyFieldTable table1 = new PropertyFieldTable(); table1.setLong("value", Long.MAX_VALUE); - Assert.assertEquals((Long) Long.MAX_VALUE, table1.getLong("value")); - - //Looking up an invalid value returns null - Assert.assertTrue(table1.getLong("Rubbish") == null); + Assert.assertTrue(table1.propertyExists("value")); - //Try reading value as a string + //Tets lookups we shouldn't get anything back for other gets + //we should get right value back for this type .... + Assert.assertEquals(null, table1.getBoolean("value")); + Assert.assertEquals(null, table1.getByte("value")); + Assert.assertEquals(null, table1.getShort("value")); + Assert.assertEquals(null, table1.getCharacter("value")); + Assert.assertEquals(null, table1.getDouble("value")); + Assert.assertEquals(null, table1.getFloat("value")); + Assert.assertEquals(null, table1.getInteger("value")); + Assert.assertEquals(Long.MAX_VALUE, (long) table1.getLong("value")); + Assert.assertEquals(null, table1.getBytes("value")); + + //... and a the string value of it. Assert.assertEquals("" + Long.MAX_VALUE, table1.getString("value")); - } + //Try setting a null value and read it back + table1.put(PropertyFieldTable.Prefix.AMQP_LONG_PROPERTY_PREFIX, "value", null); - public void testBytesLookup() - { - PropertyFieldTable table1 = new PropertyFieldTable(); - byte[] bytes = {99, 98, 97, 96, 95}; - table1.setBytes("bytes", bytes); - assertBytesEqual(bytes, table1.getBytes("bytes")); + Assert.assertEquals(null, table1.getLong("value")); + + //but still contains the value + Assert.assertTrue(table1.containsKey("value")); + + table1.remove("value"); + //but after a remove it doesn't + Assert.assertFalse(table1.containsKey("value")); + + // Table should now have zero size for encoding + checkEmpty(table1); //Looking up an invalid value returns null - Assert.assertTrue(table1.getBytes("Rubbish") == null); + Assert.assertEquals(null, table1.getLong("Rubbish")); } - // Failed Lookups - public void testFailedBooleanLookup() + /** + * Set a double and check that we can only get it back as a double + * Check that attempting to lookup a non existent value returns null + */ + public void testBytes() { - PropertyFieldTable table1 = new PropertyFieldTable(); - Assert.assertEquals(null, table1.getBoolean("int")); - } + byte[] bytes = {99, 98, 97, 96, 95}; - public void testFailedByteLookup() - { PropertyFieldTable table1 = new PropertyFieldTable(); - Assert.assertEquals(null, table1.getByte("int")); - } + table1.setBytes("value", bytes); + Assert.assertTrue(table1.propertyExists("value")); - public void testFailedBytesLookup() - { - PropertyFieldTable table1 = new PropertyFieldTable(); - Assert.assertEquals(null, table1.getBytes("int")); - } + //Tets lookups we shouldn't get anything back for other gets + //we should get right value back for this type .... + Assert.assertEquals(null, table1.getBoolean("value")); + Assert.assertEquals(null, table1.getByte("value")); + Assert.assertEquals(null, table1.getShort("value")); + Assert.assertEquals(null, table1.getCharacter("value")); + Assert.assertEquals(null, table1.getDouble("value")); + Assert.assertEquals(null, table1.getFloat("value")); + Assert.assertEquals(null, table1.getInteger("value")); + Assert.assertEquals(null, table1.getLong("value")); + assertBytesEqual(bytes, table1.getBytes("value")); - public void testFailedCharLookup() - { - PropertyFieldTable table1 = new PropertyFieldTable(); - Assert.assertEquals(null, table1.getCharacter("int")); - } + //... and a the string value of it is null + Assert.assertEquals(null, table1.getString("value")); - public void testFailedDoubleLookup() - { - PropertyFieldTable table1 = new PropertyFieldTable(); - Assert.assertEquals(null, table1.getDouble("int")); - } + //Try setting a null value and read it back + table1.put(PropertyFieldTable.Prefix.AMQP_BINARY_PROPERTY_PREFIX, "value", null); - public void testFailedFloatLookup() - { - PropertyFieldTable table1 = new PropertyFieldTable(); - Assert.assertEquals(null, table1.getFloat("int")); - } + Assert.assertEquals(null, table1.getBytes("value")); - public void testFailedIntLookup() - { - PropertyFieldTable table1 = new PropertyFieldTable(); - Assert.assertEquals(null, table1.getInteger("int")); + //but still contains the value + Assert.assertTrue(table1.containsKey("value")); + + table1.remove("value"); + //but after a remove it doesn't + Assert.assertFalse(table1.containsKey("value")); + + // Table should now have zero size for encoding + checkEmpty(table1); + + //Looking up an invalid value returns null + Assert.assertEquals(null, table1.getBytes("Rubbish")); } - public void testFailedLongLookup() + /** + * Calls all methods that can be used to check the table is empty + * - getEncodedSize + * - isEmpty + * - size + * + * @param table to check is empty + */ + private void checkEmpty(PropertyFieldTable table) { - PropertyFieldTable table1 = new PropertyFieldTable(); - Assert.assertEquals(null, table1.getLong("int")); + Assert.assertEquals(0, table.getEncodedSize()); + Assert.assertTrue(table.isEmpty()); + Assert.assertEquals(0, table.size()); + + Assert.assertEquals(0, table.keySet().size()); + Assert.assertEquals(0, table.values().size()); + Assert.assertEquals(0, table.entrySet().size()); } - public void testFailedShortLookup() + + /** + * Set a String and check that we can only get it back as a String + * Check that attempting to lookup a non existent value returns null + */ + public void testString() { PropertyFieldTable table1 = new PropertyFieldTable(); - Assert.assertEquals(null, table1.getShort("int")); + table1.setString("value", "Hello"); + Assert.assertTrue(table1.propertyExists("value")); + + //Tets lookups we shouldn't get anything back for other gets + //we should get right value back for this type .... + Assert.assertEquals(null, table1.getBoolean("value")); + Assert.assertEquals(null, table1.getByte("value")); + Assert.assertEquals(null, table1.getShort("value")); + Assert.assertEquals(null, table1.getCharacter("value")); + Assert.assertEquals(null, table1.getDouble("value")); + Assert.assertEquals(null, table1.getFloat("value")); + Assert.assertEquals(null, table1.getInteger("value")); + Assert.assertEquals(null, table1.getLong("value")); + Assert.assertEquals(null, table1.getBytes("value")); + Assert.assertEquals("Hello", table1.getString("value")); + + //Try setting a null value and read it back + table1.setString("value", null); + + Assert.assertEquals(null, table1.getString("value")); + + //but still contains the value + Assert.assertTrue(table1.containsKey("value")); + + table1.remove("value"); + //but after a remove it doesn't + Assert.assertFalse(table1.containsKey("value")); + + checkEmpty(table1); + + //Looking up an invalid value returns null + Assert.assertEquals(null, table1.getString("Rubbish")); + + //Additional Test that haven't been covered for string + table1.setObject("value", "Hello"); + //Check that it was set correctly + Assert.assertEquals("Hello", table1.getString("value")); } - public void testXML() + + /** + * Test that the generated XML can be used to create a field table with the same values. + */ + public void testValidXML() { PropertyFieldTable table1 = new PropertyFieldTable(); table1.setBoolean("bool", true); @@ -249,6 +578,8 @@ public class PropertyFieldTableTest extends TestCase table1.setInteger("int", Integer.MAX_VALUE); table1.setLong("long", Long.MAX_VALUE); table1.setShort("short", Short.MAX_VALUE); + table1.setString("string", "Hello"); + table1.setString("null-string", null); table1.setObject("object-bool", true); table1.setObject("object-byte", Byte.MAX_VALUE); @@ -259,14 +590,48 @@ public class PropertyFieldTableTest extends TestCase table1.setObject("object-int", Integer.MAX_VALUE); table1.setObject("object-long", Long.MAX_VALUE); table1.setObject("object-short", Short.MAX_VALUE); + table1.setObject("object-string", "Hello"); + + Assert.assertEquals(21, table1.size()); String table1XML = table1.toString(); PropertyFieldTable table2 = new PropertyFieldTable(table1XML); Assert.assertEquals(table1XML, table2.toString()); + + //Check that when bytes is written out as a string with no new line between items that it is read in ok. + + } + + /** + * Test that invalid input throws the correct Exception + */ + public void testInvalidXML() + { + try + { + _logger.warn("Testing Invalid XML expecting IllegalArgumentException"); + new PropertyFieldTable("Rubbish"); + fail("IllegalArgumentException expected"); + } + catch (IllegalArgumentException iae) + { + //normal path + } + try + { + _logger.warn("Testing Invalid XML expecting IllegalArgumentException"); + new PropertyFieldTable(""); + fail("IllegalArgumentException expected"); + } + catch (IllegalArgumentException iae) + { + //normal path + } } + public void testKeyEnumeration() { PropertyFieldTable table = new PropertyFieldTable(); @@ -298,6 +663,8 @@ public class PropertyFieldTableTest extends TestCase table.setInteger("int", Integer.MAX_VALUE); table.setLong("long", Long.MAX_VALUE); table.setShort("short", Short.MAX_VALUE); + table.setString("string", "Hello"); + table.setString("null-string", null); table.setObject("object-bool", true); table.setObject("object-byte", Byte.MAX_VALUE); @@ -308,6 +675,7 @@ public class PropertyFieldTableTest extends TestCase table.setObject("object-int", Integer.MAX_VALUE); table.setObject("object-long", Long.MAX_VALUE); table.setObject("object-short", Short.MAX_VALUE); + table.setObject("object-string", "Hello"); Assert.assertEquals((Boolean) true, table.getBoolean("bool")); @@ -319,6 +687,8 @@ public class PropertyFieldTableTest extends TestCase Assert.assertEquals((Integer) Integer.MAX_VALUE, table.getInteger("int")); Assert.assertEquals((Long) Long.MAX_VALUE, table.getLong("long")); Assert.assertEquals((Short) Short.MAX_VALUE, table.getShort("short")); + Assert.assertEquals("Hello", table.getString("string")); + Assert.assertEquals(null, table.getString("null-string")); Assert.assertEquals(true, table.getObject("object-bool")); Assert.assertEquals(Byte.MAX_VALUE, table.getObject("object-byte")); @@ -329,6 +699,7 @@ public class PropertyFieldTableTest extends TestCase Assert.assertEquals(Integer.MAX_VALUE, table.getObject("object-int")); Assert.assertEquals(Long.MAX_VALUE, table.getObject("object-long")); Assert.assertEquals(Short.MAX_VALUE, table.getObject("object-short")); + Assert.assertEquals("Hello", table.getObject("object-string")); } @@ -347,6 +718,8 @@ public class PropertyFieldTableTest extends TestCase table.setInteger("int", Integer.MAX_VALUE); table.setLong("long", Long.MAX_VALUE); table.setShort("short", Short.MAX_VALUE); + table.setString("string", "hello"); + table.setString("null-string", null); final ByteBuffer buffer = ByteBuffer.allocate((int) table.getEncodedSize()); // FIXME XXX: Is cast a problem? @@ -370,6 +743,9 @@ public class PropertyFieldTableTest extends TestCase Assert.assertEquals((Integer) Integer.MAX_VALUE, table2.getInteger("int")); Assert.assertEquals((Long) Long.MAX_VALUE, table2.getLong("long")); Assert.assertEquals((Short) Short.MAX_VALUE, table2.getShort("short")); + Assert.assertEquals("hello", table2.getString("string")); + Assert.assertEquals(null, table2.getString("null-string")); + } catch (AMQFrameDecodingException e) { @@ -380,7 +756,7 @@ public class PropertyFieldTableTest extends TestCase public void testEncodingSize() { - FieldTable result = FieldTableFactory.newFieldTable(); + PropertyFieldTable result = new PropertyFieldTable(); int size = 0; result.setBoolean("boolean", true); @@ -468,63 +844,296 @@ public class PropertyFieldTableTest extends TestCase } - public void testEncodingSize1() +// public void testEncodingSize1() +// { +// PropertyFieldTable table = new PropertyFieldTable(); +// int size = 0; +// result.put("one", 1L); +// size = EncodingUtils.encodedShortStringLength("one"); +// size += 1 + EncodingUtils.encodedLongLength(); +// assertEquals(size, result.getEncodedSize()); +// +// result.put("two", 2L); +// size += EncodingUtils.encodedShortStringLength("two"); +// size += 1 + EncodingUtils.encodedLongLength(); +// assertEquals(size, result.getEncodedSize()); +// +// result.put("three", 3L); +// size += EncodingUtils.encodedShortStringLength("three"); +// size += 1 + EncodingUtils.encodedLongLength(); +// assertEquals(size, result.getEncodedSize()); +// +// result.put("four", 4L); +// size += EncodingUtils.encodedShortStringLength("four"); +// size += 1 + EncodingUtils.encodedLongLength(); +// assertEquals(size, result.getEncodedSize()); +// +// result.put("five", 5L); +// size += EncodingUtils.encodedShortStringLength("five"); +// size += 1 + EncodingUtils.encodedLongLength(); +// assertEquals(size, result.getEncodedSize()); +// +// //fixme should perhaps be expanded to incorporate all types. +// +// final ByteBuffer buffer = ByteBuffer.allocate((int) result.getEncodedSize()); // FIXME XXX: Is cast a problem? +// +// result.writeToBuffer(buffer); +// +// buffer.flip(); +// +// long length = buffer.getUnsignedInt(); +// +// try +// { +// PropertyFieldTable table2 = new PropertyFieldTable(buffer, length); +// +// Assert.assertEquals((Long) 1L, table2.getLong("one")); +// Assert.assertEquals((Long) 2L, table2.getLong("two")); +// Assert.assertEquals((Long) 3L, table2.getLong("three")); +// Assert.assertEquals((Long) 4L, table2.getLong("four")); +// Assert.assertEquals((Long) 5L, table2.getLong("five")); +// } +// catch (AMQFrameDecodingException e) +// { +// e.printStackTrace(); +// fail("PFT should be instantiated from bytes." + e.getCause()); +// } +// +// } + + + /** + * Additional test for setObject + */ + public void testSetObject() { - FieldTable result = FieldTableFactory.newFieldTable(); - int size = 0; - result.put("one", 1L); - size = EncodingUtils.encodedShortStringLength("one"); - size += 1 + EncodingUtils.encodedLongLength(); - assertEquals(size, result.getEncodedSize()); + PropertyFieldTable table = new PropertyFieldTable(); + + //Try setting a non primative object + + try + { + table.setObject("value", this); + fail("Only primative values allowed in setObject"); + } + catch (AMQPInvalidClassException iae) + { + //normal path + } + // so size should be zero + Assert.assertEquals(0, table.getEncodedSize()); + } - result.put("two", 2L); - size += EncodingUtils.encodedShortStringLength("two"); - size += 1 + EncodingUtils.encodedLongLength(); - assertEquals(size, result.getEncodedSize()); + /** + * Additional test checkPropertyName doesn't accept Null + */ + public void testCheckPropertyNameasNull() + { + PropertyFieldTable table = new PropertyFieldTable(); - result.put("three", 3L); - size += EncodingUtils.encodedShortStringLength("three"); - size += 1 + EncodingUtils.encodedLongLength(); - assertEquals(size, result.getEncodedSize()); + try + { + table.setObject(null, "String"); + fail("Null property name is not allowed"); + } + catch (IllegalArgumentException iae) + { + //normal path + } + // so size should be zero + Assert.assertEquals(0, table.getEncodedSize()); + } - result.put("four", 4L); - size += EncodingUtils.encodedShortStringLength("four"); - size += 1 + EncodingUtils.encodedLongLength(); - assertEquals(size, result.getEncodedSize()); - result.put("five", 5L); - size += EncodingUtils.encodedShortStringLength("five"); - size += 1 + EncodingUtils.encodedLongLength(); - assertEquals(size, result.getEncodedSize()); + /** + * Additional test checkPropertyName doesn't accept an empty String + */ + public void testCheckPropertyNameasEmptyString() + { + PropertyFieldTable table = new PropertyFieldTable(); - //fixme should perhaps be expanded to incorporate all types. + try + { + table.setObject("", "String"); + fail("empty property name is not allowed"); + } + catch (IllegalArgumentException iae) + { + //normal path + } + // so size should be zero + Assert.assertEquals(0, table.getEncodedSize()); + } - final ByteBuffer buffer = ByteBuffer.allocate((int) result.getEncodedSize()); // FIXME XXX: Is cast a problem? - result.writeToBuffer(buffer); + /** + * Additional test checkPropertyName doesn't accept an empty String + */ + public void testCheckPropertyNamehasMaxLength() + { + PropertyFieldTable table = new PropertyFieldTable(); - buffer.flip(); + StringBuffer longPropertyName = new StringBuffer(129); - long length = buffer.getUnsignedInt(); + for (int i = 0; i < 129; i++) + { + longPropertyName.append("x"); + } try { - PropertyFieldTable table2 = new PropertyFieldTable(buffer, length); + table.setObject(longPropertyName.toString(), "String"); + fail("property name must be < 128 characters"); + } + catch (IllegalArgumentException iae) + { + //normal path + } + // so size should be zero + Assert.assertEquals(0, table.getEncodedSize()); + } + - Assert.assertEquals((Long) 1L, table2.getLong("one")); - Assert.assertEquals((Long) 2L, table2.getLong("two")); - Assert.assertEquals((Long) 3L, table2.getLong("three")); - Assert.assertEquals((Long) 4L, table2.getLong("four")); - Assert.assertEquals((Long) 5L, table2.getLong("five")); + /** + * Additional test checkPropertyName starts with a letter + */ + public void testCheckPropertyNameStartCharacterIsLetter() + { + PropertyFieldTable table = new PropertyFieldTable(); + + //Try a name that starts with a number + try + { + table.setObject("1", "String"); + fail("property name must start with a letter"); } - catch (AMQFrameDecodingException e) + catch (IllegalArgumentException iae) { - e.printStackTrace(); - fail("PFT should be instantiated from bytes." + e.getCause()); + //normal path } + // so size should be zero + Assert.assertEquals(0, table.getEncodedSize()); + } + + + /** + * Additional test checkPropertyName starts with a hash or a dollar + */ + public void testCheckPropertyNameStartCharacterIsHashorDollar() + { + PropertyFieldTable table = new PropertyFieldTable(); + //Try a name that starts with a number + try + { + table.setObject("#", "String"); + table.setObject("$", "String"); + } + catch (IllegalArgumentException iae) + { + fail("property name are allowed to start with # and $s"); + } } + + /** + * Additional test to test the contents of the table + */ + public void testContents() + { + PropertyFieldTable table = new PropertyFieldTable(); + + table.put("StringProperty", "String"); + + Assert.assertTrue(table.containsValue("String")); + + Assert.assertEquals("String", table.get("StringProperty")); + + //Test Clear + + table.clear(); + + checkEmpty(table); + } + + /** + * Test the contents of the sets + */ + public void testSets() + { + + PropertyFieldTable table = new PropertyFieldTable(); + + table.put("n1", "1"); + table.put("n2", "2"); + table.put("n3", "3"); + + Iterator iterator = table.keySet().iterator(); + Assert.assertEquals("n1", iterator.next()); + Assert.assertEquals("n2", iterator.next()); + Assert.assertEquals("n3", iterator.next()); + Assert.assertFalse(iterator.hasNext()); + + + iterator = table.values().iterator(); + Assert.assertEquals("1", iterator.next()); + Assert.assertEquals("2", iterator.next()); + Assert.assertEquals("3", iterator.next()); + Assert.assertFalse(iterator.hasNext()); + + + iterator = table.entrySet().iterator(); + Map.Entry entry = (Map.Entry) iterator.next(); + Assert.assertEquals("n1", entry.getKey()); + Assert.assertEquals("1", entry.getValue()); + entry = (Map.Entry) iterator.next(); + Assert.assertEquals("n2", entry.getKey()); + Assert.assertEquals("2", entry.getValue()); + entry = (Map.Entry) iterator.next(); + Assert.assertEquals("n3", entry.getKey()); + Assert.assertEquals("3", entry.getValue()); + Assert.assertFalse(iterator.hasNext()); + + + } + + + /** + * Test that all the values are preserved after a putAll + */ + public void testPutAll() + { + Map map = new HashMap(); + + map.put("char", 'c'); + map.put("double", Double.MAX_VALUE); + map.put("float", Float.MAX_VALUE); + map.put("int", Integer.MAX_VALUE); + map.put("long", Long.MAX_VALUE); + map.put("short", Short.MAX_VALUE); + + PropertyFieldTable table = new PropertyFieldTable(); + + table.putAll(map); + + Assert.assertEquals(6, table.size()); + + Assert.assertTrue(table.containsKey("char")); + Assert.assertEquals('c', (char) table.getCharacter("char")); + Assert.assertTrue(table.containsKey("double")); + Assert.assertEquals(Double.MAX_VALUE, table.getDouble("double")); + Assert.assertTrue(table.containsKey("float")); + Assert.assertEquals(Float.MAX_VALUE, table.getFloat("float")); + Assert.assertTrue(table.containsKey("int")); + Assert.assertEquals(Integer.MAX_VALUE, (int) table.getInteger("int")); + Assert.assertTrue(table.containsKey("long")); + Assert.assertEquals(Long.MAX_VALUE, (long) table.getLong("long")); + Assert.assertTrue(table.containsKey("short")); + Assert.assertEquals(Short.MAX_VALUE, (short) table.getShort("short")); + Assert.assertEquals(Short.MAX_VALUE, (short) table.getShort("short")); + } + + private void assertBytesEqual(byte[] expected, byte[] actual) { Assert.assertEquals(expected.length, actual.length); |