From 1d6bec9c7ea9f4ea71a919e59010fd0744581ac9 Mon Sep 17 00:00:00 2001 From: Martin Ritchie Date: Mon, 7 May 2007 09:40:58 +0000 Subject: Merged revisions 534897-534902,534904-535253,535255-535809 via svnmerge from https://svn.apache.org/repos/asf/incubator/qpid/branches/M2 ........ r534897 | bhupendrab | 2007-05-03 15:53:20 +0100 (Thu, 03 May 2007) | 1 line Attribute details background made same as other displays. ........ r535309 | ritchiem | 2007-05-04 17:12:59 +0100 (Fri, 04 May 2007) | 2 lines QPID-466 Changes to FieldTable along with corresponding PropertyValueTest to limit the Java client to only AMQP 0-8 compliant values. ........ r535809 | ritchiem | 2007-05-07 10:28:15 +0100 (Mon, 07 May 2007) | 5 lines QPID-466 Updated FieldTable to ensure no Decimal value is set that is larger than can be transmitted over AMQP. That is a max scale value of Byte.MAX_VALUE and value of up to Integer.MAX_VALUE. Additional tests to ensure this is the case. ........ git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk@535819 13f79535-47bb-0310-9956-ffa450edef68 --- .../main/java/org/apache/qpid/framing/AMQType.java | 64 +++++--- .../java/org/apache/qpid/framing/FieldTable.java | 177 ++++++++++++--------- 2 files changed, 144 insertions(+), 97 deletions(-) (limited to 'qpid/java/common') diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQType.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQType.java index 80739e1aee..6dda91a488 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQType.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQType.java @@ -22,10 +22,11 @@ package org.apache.qpid.framing; import org.apache.mina.common.ByteBuffer; +import java.math.BigDecimal; +import java.math.BigInteger; + public enum AMQType { - - //AMQP FieldTable Wire Types LONG_STRING('S') @@ -113,55 +114,75 @@ public enum AMQType public int getEncodingSize(Object value) { - // TODO : fixme - throw new UnsupportedOperationException(); + return EncodingUtils.encodedByteLength()+ EncodingUtils.encodedIntegerLength(); } public Object toNativeValue(Object value) { - // TODO : fixme - throw new UnsupportedOperationException(); + if(value instanceof BigDecimal) + { + return (BigDecimal) value; + } + else + { + throw new NumberFormatException("Cannot convert: " + value + "(" + + value.getClass().getName() + ") to BigDecimal."); + } } public void writeValueImpl(Object value, ByteBuffer buffer) { - // TODO : fixme - throw new UnsupportedOperationException(); + BigDecimal bd = (BigDecimal) value; + + byte places = new Integer(bd.scale()).byteValue(); + + int unscaled = bd.intValue(); + + EncodingUtils.writeByte(buffer, places); + + EncodingUtils.writeInteger(buffer, unscaled); } public Object readValueFromBuffer(ByteBuffer buffer) { - // TODO : fixme - throw new UnsupportedOperationException(); + byte places = EncodingUtils.readByte(buffer); + + int unscaled = EncodingUtils.readInteger(buffer); + + BigDecimal bd = new BigDecimal(unscaled); + return bd.setScale(places); } }, TIMESTAMP('T') { - public int getEncodingSize(Object value) { - // TODO : fixme - throw new UnsupportedOperationException(); + return EncodingUtils.encodedLongLength(); } - public Object toNativeValue(Object value) { - // TODO : fixme - throw new UnsupportedOperationException(); + if(value instanceof Long) + { + return (Long) value; + } + else + { + throw new NumberFormatException("Cannot convert: " + value + "(" + + value.getClass().getName() + ") to timestamp."); + } } public void writeValueImpl(Object value, ByteBuffer buffer) { - // TODO : fixme - throw new UnsupportedOperationException(); + EncodingUtils.writeLong(buffer, (Long) value); } + public Object readValueFromBuffer(ByteBuffer buffer) { - // TODO : fixme - throw new UnsupportedOperationException(); + return EncodingUtils.readLong(buffer); } }, @@ -173,7 +194,6 @@ public enum AMQType throw new UnsupportedOperationException(); } - public Object toNativeValue(Object value) { // TODO : fixme @@ -250,7 +270,7 @@ public enum AMQType public void writeValueImpl(Object value, ByteBuffer buffer) { - EncodingUtils.writeLongstr(buffer, (byte[]) value); + EncodingUtils.writeLongstr(buffer, (byte[]) value); } public Object readValueFromBuffer(ByteBuffer buffer) diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java index a7544c5747..631a3ae149 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java @@ -27,6 +27,7 @@ import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; +import java.math.BigDecimal; import org.apache.log4j.Logger; import org.apache.mina.common.ByteBuffer; @@ -56,26 +57,28 @@ public class FieldTable * * @param buffer the buffer from which to read data. The length byte must be read already * @param length the length of the field table. Must be > 0. + * * @throws AMQFrameDecodingException if there is an error decoding the table */ public FieldTable(ByteBuffer buffer, long length) throws AMQFrameDecodingException { this(); _encodedForm = buffer.slice(); - _encodedForm.limit((int)length); + _encodedForm.limit((int) length); _encodedSize = length; - buffer.skip((int)length); + buffer.skip((int) length); } - private AMQTypedValue getProperty(AMQShortString string) { - synchronized(this) + checkPropertyName(string); + + synchronized (this) { - if(_properties == null) + if (_properties == null) { - if(_encodedForm == null) + if (_encodedForm == null) { return null; } @@ -86,7 +89,7 @@ public class FieldTable } } - if(_properties == null) + if (_properties == null) { return null; } @@ -112,17 +115,18 @@ public class FieldTable private AMQTypedValue setProperty(AMQShortString key, AMQTypedValue val) { + checkPropertyName(key); initMapIfNecessary(); - if(_properties.containsKey(key)) + if (_properties.containsKey(key)) { _encodedForm = null; - if(val == null) + if (val == null) { return removeKey(key); } } - else if(_encodedForm != null && val != null) + else if (_encodedForm != null && val != null) { EncodingUtils.writeShortStringBytes(_encodedForm, key); val.writeToBuffer(_encodedForm); @@ -134,9 +138,8 @@ public class FieldTable } - - AMQTypedValue oldVal = _properties.put(key,val); - if(oldVal != null) + AMQTypedValue oldVal = _properties.put(key, val); + if (oldVal != null) { _encodedSize -= oldVal.getEncodingSize(); } @@ -151,13 +154,13 @@ public class FieldTable private void initMapIfNecessary() { - synchronized(this) + synchronized (this) { - if(_properties == null) + if (_properties == null) { - if(_encodedForm == null || _encodedSize == 0) + if (_encodedForm == null || _encodedSize == 0) { - _properties = new LinkedHashMap(); + _properties = new LinkedHashMap(); } else { @@ -365,7 +368,7 @@ public class FieldTable public Object getObject(AMQShortString string) { AMQTypedValue value = getProperty(string); - if(value != null) + if (value != null) { return value.getValue(); } @@ -376,6 +379,33 @@ public class FieldTable } + public Long getTimestamp(AMQShortString name) + { + AMQTypedValue value = getProperty(name); + if ((value != null) && ((value.getType() == AMQType.TIMESTAMP))) + { + return (Long) value.getValue(); + } + else + { + return null; + } + } + + public BigDecimal getDecimal(AMQShortString propertyName) + { + AMQTypedValue value = getProperty(propertyName); + if ((value != null) && ((value.getType() == AMQType.DECIMAL))) + { + return (BigDecimal) value.getValue(); + } + else + { + return null; + } + } + + // ************ Setters public Object setBoolean(String string, boolean b) { @@ -384,18 +414,16 @@ public class FieldTable public Object setBoolean(AMQShortString string, boolean b) { - checkPropertyName(string); return setProperty(string, AMQType.BOOLEAN.asTypedValue(b)); } public Object setByte(String string, byte b) { return setByte(new AMQShortString(string), b); - } + } public Object setByte(AMQShortString string, byte b) { - checkPropertyName(string); return setProperty(string, AMQType.BYTE.asTypedValue(b)); } @@ -406,7 +434,6 @@ public class FieldTable public Object setShort(AMQShortString string, short i) { - checkPropertyName(string); return setProperty(string, AMQType.SHORT.asTypedValue(i)); } @@ -418,7 +445,6 @@ public class FieldTable public Object setInteger(AMQShortString string, int i) { - checkPropertyName(string); return setProperty(string, AMQType.INT.asTypedValue(i)); } @@ -430,11 +456,9 @@ public class FieldTable public Object setLong(AMQShortString string, long l) { - checkPropertyName(string); return setProperty(string, AMQType.LONG.asTypedValue(l)); } - public Object setFloat(String string, float f) { return setFloat(new AMQShortString(string), f); @@ -442,7 +466,6 @@ public class FieldTable public Object setFloat(AMQShortString string, float v) { - checkPropertyName(string); return setProperty(string, AMQType.FLOAT.asTypedValue(v)); } @@ -451,14 +474,11 @@ public class FieldTable return setDouble(new AMQShortString(string), d); } - public Object setDouble(AMQShortString string, double v) { - checkPropertyName(string); return setProperty(string, AMQType.DOUBLE.asTypedValue(v)); } - public Object setString(String string, String s) { return setString(new AMQShortString(string), s); @@ -466,7 +486,6 @@ public class FieldTable public Object setAsciiString(AMQShortString string, String value) { - checkPropertyName(string); if (value == null) { return setProperty(string, AMQType.VOID.asTypedValue(null)); @@ -479,7 +498,6 @@ public class FieldTable public Object setString(AMQShortString string, String value) { - checkPropertyName(string); if (value == null) { return setProperty(string, AMQType.VOID.asTypedValue(null)); @@ -490,20 +508,16 @@ public class FieldTable } } - public Object setChar(String string, char c) { return setChar(new AMQShortString(string), c); } - public Object setChar(AMQShortString string, char c) { - checkPropertyName(string); return setProperty(string, AMQType.ASCII_CHARACTER.asTypedValue(c)); } - public Object setBytes(String string, byte[] b) { return setBytes(new AMQShortString(string), b); @@ -511,20 +525,18 @@ public class FieldTable public Object setBytes(AMQShortString string, byte[] bytes) { - checkPropertyName(string); return setProperty(string, AMQType.BINARY.asTypedValue(bytes)); } public Object setBytes(String string, byte[] bytes, int start, int length) { - return setBytes(new AMQShortString(string), bytes,start,length); + return setBytes(new AMQShortString(string), bytes, start, length); } public Object setBytes(AMQShortString string, byte[] bytes, int start, int length) { - checkPropertyName(string); byte[] newBytes = new byte[length]; - System.arraycopy(bytes,start,newBytes,0,length); + System.arraycopy(bytes, start, newBytes, 0, length); return setBytes(string, bytes); } @@ -533,6 +545,31 @@ public class FieldTable return setObject(new AMQShortString(string), o); } + public Object setTimestamp(AMQShortString string, long datetime) + { + return setProperty(string, AMQType.TIMESTAMP.asTypedValue(datetime)); + } + + public Object setDecimal(AMQShortString string, BigDecimal decimal) + { + if (decimal.longValue() > Integer.MAX_VALUE) + { + throw new UnsupportedOperationException("AMQP doesnot support decimals larger than " + Integer.MAX_VALUE); + } + + if (decimal.scale() > Byte.MAX_VALUE) + { + throw new UnsupportedOperationException("AMQP doesnot support decimal scales larger than " + Byte.MAX_VALUE); + } + + return setProperty(string, AMQType.DECIMAL.asTypedValue(decimal)); + } + + public Object setVoid(AMQShortString string) + { + return setProperty(string, AMQType.VOID.asTypedValue(null)); + } + public Object setObject(AMQShortString string, Object object) { if (object instanceof Boolean) @@ -579,7 +616,6 @@ public class FieldTable throw new AMQPInvalidClassException("Only Primatives objects allowed Object is:" + object.getClass()); } - public boolean isNullStringValue(String name) { AMQTypedValue value = getProperty(new AMQShortString(name)); @@ -603,10 +639,11 @@ public class FieldTable return itemExists(propertyName); } - public boolean itemExists(AMQShortString string) + public boolean itemExists(AMQShortString propertyName) { + checkPropertyName(propertyName); initMapIfNecessary(); - return _properties.containsKey(string); + return _properties.containsKey(propertyName); } public boolean itemExists(String string) @@ -620,15 +657,13 @@ public class FieldTable return _properties.toString(); } - - private void checkPropertyName(AMQShortString propertyName) { if (propertyName == null) { throw new IllegalArgumentException("Property name must not be null"); } - else if (propertyName.length()==0) + else if (propertyName.length() == 0) { throw new IllegalArgumentException("Property name must not be the empty string"); } @@ -636,7 +671,6 @@ public class FieldTable checkIdentiferFormat(propertyName); } - protected static void checkIdentiferFormat(AMQShortString propertyName) { // AMQP Spec: 4.2.5.5 Field Tables @@ -649,7 +683,6 @@ public class FieldTable // 503 (syntax error). Conformance test: amq_wlp_table_01. // * A peer MUST handle duplicate fields by using only the first instance. - // AMQP length limit if (propertyName.length() > 128) { @@ -666,7 +699,6 @@ public class FieldTable } } - // ************************* Byte Buffer Processing public void writeToBuffer(ByteBuffer buffer) @@ -707,9 +739,9 @@ public class FieldTable { int encodedSize = 0; - if(_properties != null) + if (_properties != null) { - for(Map.Entry e : _properties.entrySet()) + for (Map.Entry e : _properties.entrySet()) { encodedSize += EncodingUtils.encodedShortStringLength(e.getKey()); encodedSize++; // the byte for the encoding Type @@ -732,18 +764,19 @@ public class FieldTable public static interface FieldTableElementProcessor { public boolean processElement(String propertyName, AMQTypedValue value); + public Object getResult(); } public Object processOverElements(FieldTableElementProcessor processor) { initMapIfNecessary(); - if(_properties != null) + if (_properties != null) { - for(Map.Entry e : _properties.entrySet()) + for (Map.Entry e : _properties.entrySet()) { boolean result = processor.processElement(e.getKey().toString(), e.getValue()); - if(!result) + if (!result) { break; } @@ -764,7 +797,7 @@ public class FieldTable public boolean isEmpty() { - return size() ==0; + return size() == 0; } public boolean containsKey(AMQShortString key) @@ -782,7 +815,7 @@ public class FieldTable { initMapIfNecessary(); Set keys = new LinkedHashSet(); - for(AMQShortString key : _properties.keySet()) + for (AMQShortString key : _properties.keySet()) { keys.add(key.toString()); } @@ -797,7 +830,6 @@ public class FieldTable } - public Object put(AMQShortString key, Object value) { return setObject(key, value); @@ -824,7 +856,7 @@ public class FieldTable initMapIfNecessary(); _encodedForm = null; AMQTypedValue value = _properties.remove(key); - if(value == null) + if (value == null) { return null; } @@ -839,11 +871,10 @@ public class FieldTable } - public void clear() { initMapIfNecessary(); - _encodedForm = null; + _encodedForm = null; _properties.clear(); _encodedSize = 0; } @@ -857,19 +888,19 @@ public class FieldTable private void putDataInBuffer(ByteBuffer buffer) { - if(_encodedForm != null) + if (_encodedForm != null) { - if(_encodedForm.position() != 0) + if (_encodedForm.position() != 0) { _encodedForm.flip(); } // _encodedForm.limit((int)getEncodedSize()); buffer.put(_encodedForm); } - else if(_properties != null) + else if (_properties != null) { - final Iterator> it = _properties.entrySet().iterator(); + final Iterator> it = _properties.entrySet().iterator(); //If there are values then write out the encoded Size... could check _encodedSize != 0 // write out the total length, which we have kept up to date as data is added @@ -877,7 +908,7 @@ public class FieldTable while (it.hasNext()) { - final Map.Entry me = it.next(); + final Map.Entry me = it.next(); try { if (_logger.isTraceEnabled()) @@ -889,8 +920,6 @@ public class FieldTable " Remaining:" + buffer.remaining()); } - - //Write the actual parameter name EncodingUtils.writeShortStringBytes(buffer, me.getKey()); me.getValue().writeToBuffer(buffer); @@ -917,12 +946,12 @@ public class FieldTable { final boolean trace = _logger.isTraceEnabled(); - if(length > 0) + if (length > 0) { - final int expectedRemaining = buffer.remaining()-(int)length; + final int expectedRemaining = buffer.remaining() - (int) length; - _properties = new LinkedHashMap(INITIAL_HASHMAP_CAPACITY); + _properties = new LinkedHashMap(INITIAL_HASHMAP_CAPACITY); do { @@ -936,11 +965,9 @@ public class FieldTable } - - _properties.put(key,value); + _properties.put(key, value); - } while (buffer.remaining() > expectedRemaining); @@ -962,15 +989,15 @@ public class FieldTable public boolean equals(Object o) { - if(o == this) + if (o == this) { return true; } - if(o == null) + if (o == null) { return false; } - if(!(o instanceof FieldTable)) + if (!(o instanceof FieldTable)) { return false; } -- cgit v1.2.1