From a96152eea7e7ce48bb9340f477f3935744ee5ea6 Mon Sep 17 00:00:00 2001 From: Martin Ritchie Date: Fri, 15 Dec 2006 08:33:10 +0000 Subject: 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 --- .../org/apache/qpid/AMQPInvalidClassException.java | 30 + .../qpid/framing/BasicContentHeaderProperties.java | 25 + .../org/apache/qpid/framing/EncodingUtils.java | 10 +- .../apache/qpid/framing/JMSPropertyFieldTable.java | 514 +++++++++++++++ .../apache/qpid/framing/PropertyFieldTable.java | 711 +++++++++------------ .../src/main/java/org/apache/qpid/pool/Event.java | 2 +- 6 files changed, 882 insertions(+), 410 deletions(-) create mode 100644 java/common/src/main/java/org/apache/qpid/AMQPInvalidClassException.java create mode 100644 java/common/src/main/java/org/apache/qpid/framing/JMSPropertyFieldTable.java (limited to 'java/common/src/main') 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 _properties; - private LinkedHashMap _propertyNamesTypeMap; - private long _encodedSize = 0;//EncodingUtils.unsignedIntegerLength(); + private LinkedHashMap _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 _reverseTypeMap = new HashMap(); public PropertyFieldTable() { super(); _properties = new LinkedHashMap(); - _propertyNamesTypeMap = new LinkedHashMap(); + _propertyNamesTypeMap = new LinkedHashMap(); } 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(" 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; } } -- cgit v1.2.1