summaryrefslogtreecommitdiff
path: root/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/common/src/main/java/org/apache/qpid/framing/FieldTable.java')
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/FieldTable.java393
1 files changed, 86 insertions, 307 deletions
diff --git a/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java b/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java
index 796e1843af..44d0268561 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java
@@ -1,317 +1,96 @@
/*
+ * 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
*
- * 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.
+ * 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.log4j.Logger;
import org.apache.mina.common.ByteBuffer;
-import java.util.*;
-
-/**
- * From the protocol document:
- * field-table = short-integer *field-value-pair
- * field-value-pair = field-name field-value
- * field-name = short-string
- * field-value = 'S' long-string
- * / 'I' long-integer
- * / 'D' decimal-value
- * / 'T' long-integer
- * decimal-value = decimals long-integer
- * decimals = OCTET
- */
-public class FieldTable extends LinkedHashMap
+import java.util.Map;
+import java.util.Enumeration;
+
+public interface FieldTable extends Map
{
- private static final Logger _logger = Logger.getLogger(FieldTable.class);
- private long _encodedSize = 0;
-
- public FieldTable()
- {
- super();
- }
-
- /**
- * Construct a new field table.
- *
- * @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
- {
- super();
- final boolean debug = _logger.isDebugEnabled();
- assert length > 0;
- _encodedSize = length;
- int sizeRead = 0;
- while (sizeRead < _encodedSize)
- {
- 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;
- switch (type)
- {
- case'S':
- value = EncodingUtils.readLongString(buffer);
- break;
- case'I':
- value = new Long(buffer.getUnsignedInt());
- break;
- default:
- String msg = "Field '" + key + "' - unsupported field table type: " + type;
- //some extra debug information...
- msg += " (" + iType + "), length=" + length + ", sizeRead=" + sizeRead + ", sizeRemaining=" + sizeRemaining;
- throw new AMQFrameDecodingException(msg);
- }
- sizeRead += (sizeRemaining - buffer.remaining());
-
- if (debug)
- {
- _logger.debug("FieldTable::FieldTable(buffer," + length + "): Read type '" + type + "', key '" + key + "', value '" + value + "' (now read " + sizeRead + " of " + length + " encoded bytes)...");
- }
-
- // we deliberately want to call put in the parent class since we do
- // not need to do the size calculations
- super.put(key, value);
- }
-
- if (debug)
- {
- _logger.debug("FieldTable::FieldTable(buffer," + length + "): Done.");
- }
- }
-
- public void writeToBuffer(ByteBuffer buffer)
- {
- final boolean debug = _logger.isDebugEnabled();
-
- if (debug)
- {
- _logger.debug("FieldTable::writeToBuffer: Writing encoded size of " + _encodedSize + "...");
- }
-
- // write out the total length, which we have kept up to date as data is added
- EncodingUtils.writeUnsignedInteger(buffer, _encodedSize);
- final Iterator it = this.entrySet().iterator();
- while (it.hasNext())
- {
- Map.Entry me = (Map.Entry) it.next();
- String key = (String) me.getKey();
-
- EncodingUtils.writeShortStringBytes(buffer, key);
- Object value = me.getValue();
-
- if (debug)
- {
- _logger.debug("FieldTable::writeToBuffer: Writing key '" + key + "' of type " + value.getClass() + ", value '" + value + "'...");
- }
-
- if (value instanceof byte[])
- {
- buffer.put((byte) 'S');
- EncodingUtils.writeLongstr(buffer, (byte[]) value);
- }
- else if (value instanceof String)
- {
- // TODO: look at using proper charset encoder
- buffer.put((byte) 'S');
- EncodingUtils.writeLongStringBytes(buffer, (String) value);
- }
- else if (value instanceof Long)
- {
- // TODO: look at using proper charset encoder
- buffer.put((byte) 'I');
- EncodingUtils.writeUnsignedInteger(buffer, ((Long) value).longValue());
- }
- else
- {
- // Should never get here
- throw new IllegalArgumentException("Key '" + key + "': Unsupported type in field table, type: " + ((value == null) ? "null-object" : value.getClass()));
- }
- }
-
- if (debug)
- {
- _logger.debug("FieldTable::writeToBuffer: Done.");
- }
- }
-
- public byte[] getDataAsBytes()
- {
- final ByteBuffer buffer = ByteBuffer.allocate((int) _encodedSize); // XXX: Is cast a problem?
- final Iterator it = this.entrySet().iterator();
- while (it.hasNext())
- {
- Map.Entry me = (Map.Entry) it.next();
- String key = (String) me.getKey();
- EncodingUtils.writeShortStringBytes(buffer, key);
- Object value = me.getValue();
- if (value instanceof byte[])
- {
- buffer.put((byte) 'S');
- EncodingUtils.writeLongstr(buffer, (byte[]) value);
- }
- else if (value instanceof String)
- {
- // TODO: look at using proper charset encoder
- buffer.put((byte) 'S');
- EncodingUtils.writeLongStringBytes(buffer, (String) value);
- }
- else if (value instanceof char[])
- {
- // TODO: look at using proper charset encoder
- buffer.put((byte) 'S');
- EncodingUtils.writeLongStringBytes(buffer, (char[]) value);
- }
- else if (value instanceof Long || value instanceof Integer)
- {
- // TODO: look at using proper charset encoder
- buffer.put((byte) 'I');
- EncodingUtils.writeUnsignedInteger(buffer, ((Long) value).longValue());
- }
- else
- {
- // Should never get here
- assert false;
- }
- }
- final byte[] result = new byte[(int) _encodedSize];
- buffer.flip();
- buffer.get(result);
- buffer.release();
- return result;
- }
-
- public Object put(Object key, Object value)
- {
- final boolean debug = _logger.isDebugEnabled();
-
- if (key == null)
- {
- throw new IllegalArgumentException("All keys must be Strings - was passed: null");
- }
- else if (!(key instanceof String))
- {
- throw new IllegalArgumentException("All keys must be Strings - was passed: " + key.getClass());
- }
-
- Object existing;
-
- if ((existing = super.remove(key)) != null)
- {
- if (debug)
- {
- _logger.debug("Found duplicate of key '" + key + "', previous value '" + existing + "' (" + existing.getClass() + "), to be replaced by '" + value + "', (" + value.getClass() + ") - stack trace of source of duplicate follows...", new Throwable().fillInStackTrace());
- }
-
- // 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 (value == null)
- {
- _encodedSize -= EncodingUtils.encodedShortStringLength((String) key);
- }
-
- // 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(existing);
- }
- else
- {
- if (value != null)
- {
- _encodedSize += EncodingUtils.encodedShortStringLength((String) key);
- }
- }
-
- // 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.
- if (value != null)
- {
- _encodedSize += getEncodingSize(value);
- }
-
- return super.put(key, value);
- }
-
- public Object remove(Object key)
- {
- if (super.containsKey(key))
- {
- final Object value = super.remove(key);
- _encodedSize -= EncodingUtils.encodedShortStringLength((String) key);
-
- // This check is, for now, unnecessary (we don't store null values).
- if (value != null)
- {
- _encodedSize -= getEncodingSize(value);
- }
-
- return value;
- }
- else
- {
- return null;
- }
- }
-
- /**
- * @return unsigned integer
- */
- public long getEncodedSize()
- {
- return _encodedSize;
- }
-
- /**
- * @return integer
- */
- private static int getEncodingSize(Object value)
- {
- int encodingSize;
-
- // the extra byte if for the type indicator that is written out
- if (value instanceof String)
- {
- encodingSize = 1 + EncodingUtils.encodedLongStringLength((String) value);
- }
- else if (value instanceof char[])
- {
- encodingSize = 1 + EncodingUtils.encodedLongStringLength((char[]) value);
- }
- else if (value instanceof Integer)
- {
- encodingSize = 1 + 4;
- }
- else if (value instanceof Long)
- {
- encodingSize = 1 + 4;
- }
- else
- {
- throw new IllegalArgumentException("Unsupported type in field table: " + value.getClass());
- }
-
- return encodingSize;
- }
+ void writeToBuffer(ByteBuffer buffer);
+
+ void setFromBuffer(ByteBuffer buffer, long length) throws AMQFrameDecodingException;
+
+ byte[] getDataAsBytes();
+
+ public long getEncodedSize();
+
+ Object put(Object key, Object value);
+
+ Object remove(Object key);
+
+
+ public Enumeration getPropertyNames();
+
+ public boolean propertyExists(String propertyName);
+
+ //Getters
+
+ public Boolean getBoolean(String string);
+
+ public Byte getByte(String string);
+
+ public Short getShort(String string);
+
+ public Integer getInteger(String string);
+
+ public Long getLong(String string);
+
+ public Float getFloat(String string);
+
+ public Double getDouble(String string);
+
+ public String getString(String string);
+
+ public Character getCharacter(String string);
+
+ public byte[] getBytes(String string);
+
+ public Object getObject(String string);
+
+ // Setters
+ public Object setBoolean(String string, boolean b);
+
+ public Object setByte(String string, byte b);
+
+ public Object setShort(String string, short i);
+
+ public Object setInteger(String string, int i);
+
+ public Object setLong(String string, long l);
+
+ public Object setFloat(String string, float v);
+
+ public Object setDouble(String string, double v);
+
+ public Object setString(String string, String string1);
+
+ public Object setChar(String string, char c);
+
+ public Object setBytes(String string, byte[] bytes);
+
+ public Object setBytes(String string, byte[] bytes, int start, int length);
+
+ public Object setObject(String string, Object object);
+
}