You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by rg...@apache.org on 2006/12/22 21:32:44 UTC

svn commit: r489748 [1/2] - in /incubator/qpid/trunk/qpid/java: broker/src/main/java/org/apache/qpid/server/exchange/ broker/src/test/java/org/apache/qpid/server/exchange/ client/src/main/java/org/apache/qpid/client/ client/src/main/java/org/apache/qpi...

Author: rgreig
Date: Fri Dec 22 12:32:43 2006
New Revision: 489748

URL: http://svn.apache.org/viewvc?view=rev&rev=489748
Log:
QPID-229 : Patch supplied by Rob Godfrey - Change implementation of FieldTable

Added:
    incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQType.java
    incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypeMap.java
    incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java
Removed:
    incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/PropertyFieldTable.java
Modified:
    incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java
    incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java
    incubator/qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java
    incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java
    incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java
    incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/test/unit/message/StreamMessageTest.java
    incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java
    incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java
    incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/FieldTableFactory.java
    incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/JMSPropertyFieldTable.java
    incubator/qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/framing/BasicContentHeaderPropertiesTest.java
    incubator/qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/framing/JMSPropertyFieldTableTest.java
    incubator/qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java
    incubator/qpid/trunk/qpid/java/systests/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java
    incubator/qpid/trunk/qpid/java/systests/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java
    incubator/qpid/trunk/qpid/java/systests/src/test/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java

Modified: incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java?view=diff&rev=489748&r1=489747&r2=489748
==============================================================================
--- incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java (original)
+++ incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java Fri Dec 22 12:32:43 2006
@@ -21,12 +21,11 @@
 package org.apache.qpid.server.exchange;
 
 import org.apache.log4j.Logger;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.framing.AMQTypedValue;
 
-import java.util.Collections;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.*;
 
 /**
  * Defines binding and matching based on a set of headers.
@@ -35,11 +34,53 @@
 {
     private static final Logger _logger = Logger.getLogger(HeadersBinding.class);
 
-    private final Map _mappings = new HashMap();
-    private final Set<Object> required = new HashSet<Object>();
-    private final Set<Map.Entry> matches = new HashSet<Map.Entry>();
+    private final FieldTable _mappings = new FieldTable();
+    private final Set<String> required = new HashSet<String>();
+    private final Map<String,Object> matches = new HashMap<String,Object>();
     private boolean matchAny;
 
+    private final class MatchesOrProcessor implements FieldTable.FieldTableElementProcessor
+    {
+        private Boolean _result = Boolean.FALSE;
+
+        public boolean processElement(String propertyName, AMQTypedValue value)
+        {
+            if((value != null) && (value.getValue() != null) && value.getValue().equals(matches.get(propertyName)))
+            {
+                _result = Boolean.TRUE;
+                return false;
+            }
+            return true;
+        }
+
+        public Object getResult()
+        {
+            return _result;
+        }
+    }
+
+    private final class RequiredOrProcessor implements FieldTable.FieldTableElementProcessor
+    {
+        Boolean _result = Boolean.FALSE;
+
+        public boolean processElement(String propertyName, AMQTypedValue value)
+        {
+            if(required.contains(propertyName))
+            {
+                _result = Boolean.TRUE;
+                return false;
+            }
+            return true;
+        }
+
+        public Object getResult()
+        {
+            return _result;
+        }
+    }
+
+
+
     /**
      * Creates a binding for a set of mappings. Those mappings whose value is
      * null or the empty string are assumed only to be required headers, with
@@ -47,33 +88,50 @@
      * define a required match of value. 
      * @param mappings the defined mappings this binding should use
      */
-    HeadersBinding(Map mappings)
+
+    HeadersBinding(FieldTable mappings)
     {
-        //noinspection unchecked
-        this(mappings == null ? new HashSet<Map.Entry>() : mappings.entrySet());
-        _mappings.putAll(mappings);
+        Enumeration propertyNames = mappings.getPropertyNames();
+        while(propertyNames.hasMoreElements())
+        {
+            String propName = (String) propertyNames.nextElement();
+            _mappings.put(propName, mappings.getObject(propName));
+        }
+        initMappings();
     }
 
-    private HeadersBinding(Set<Map.Entry> entries)
+    private void initMappings()
     {
-        for (Map.Entry e : entries)
+
+        _mappings.processOverElements(new FieldTable.FieldTableElementProcessor()
         {
-            if (isSpecial(e.getKey()))
-            {
-                processSpecial((String) e.getKey(), e.getValue());
-            }
-            else if (e.getValue() == null || e.getValue().equals(""))
+
+            public boolean processElement(String propertyName, AMQTypedValue value)
             {
-                required.add(e.getKey());
+                if (isSpecial(propertyName))
+                {
+                    processSpecial(propertyName, value.getValue());
+                }
+                else if (value.getValue() == null || value.getValue().equals(""))
+                {
+                    required.add(propertyName);
+                }
+                else
+                {
+                    matches.put(propertyName,value.getValue());
+                }
+
+                return true;
             }
-            else
+
+            public Object getResult()
             {
-                matches.add(e);
+                return null;
             }
-        }
+        });
     }
 
-    protected Map getMappings()
+    protected FieldTable getMappings()
     {
         return _mappings;
     }
@@ -84,7 +142,7 @@
      * @return true if the headers define any required keys and match any required
      * values
      */
-    public boolean matches(Map headers)
+    public boolean matches(FieldTable headers)
     {
         if(headers == null)
         {
@@ -96,18 +154,37 @@
         }
     }
 
-    private boolean and(Map headers)
+    private boolean and(FieldTable headers)
     {
-        //need to match all the defined mapping rules:
-        return headers.keySet().containsAll(required)
-                && headers.entrySet().containsAll(matches);
+        if(headers.keys().containsAll(required))
+        {
+            for(Map.Entry<String, Object> e : matches.entrySet())
+            {
+                if(!e.getValue().equals(headers.getObject(e.getKey())))
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+        else
+        {
+            return false;
+        }
     }
 
-    private boolean or(Map headers)
+
+    private boolean or(final FieldTable headers)
     {
-        //only need to match one mapping rule:
-        return !Collections.disjoint(headers.keySet(), required)
-                || !Collections.disjoint(headers.entrySet(), matches);
+        if(required.isEmpty() || !(Boolean) headers.processOverElements(new RequiredOrProcessor()))
+        {
+            return ((!matches.isEmpty()) && (Boolean) headers.processOverElements(new MatchesOrProcessor()))
+                    || (required.isEmpty() && matches.isEmpty());
+        }
+        else
+        {
+            return true;
+        }
     }
 
     private void processSpecial(String key, Object value)

Modified: incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java?view=diff&rev=489748&r1=489747&r2=489748
==============================================================================
--- incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java (original)
+++ incubator/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java Fri Dec 22 12:32:43 2006
@@ -22,10 +22,7 @@
 
 import org.apache.log4j.Logger;
 import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.BasicContentHeaderProperties;
-import org.apache.qpid.framing.ContentHeaderBody;
-import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.framing.FieldTableFactory;
+import org.apache.qpid.framing.*;
 import org.apache.qpid.server.management.MBeanConstructor;
 import org.apache.qpid.server.management.MBeanDescription;
 import org.apache.qpid.server.queue.AMQMessage;
@@ -34,10 +31,7 @@
 
 import javax.management.JMException;
 import javax.management.openmbean.*;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
@@ -119,16 +113,24 @@
                 String queueName = registration.queue.getName();
 
                 HeadersBinding headers = registration.binding;
-                Map<Object, Object> headerMappings = headers.getMappings();
-                List<String> mappingList = new ArrayList<String>();
+                FieldTable headerMappings = headers.getMappings();
+                final List<String> mappingList = new ArrayList<String>();
 
-                for (Map.Entry<Object, Object> en : headerMappings.entrySet())
+                headerMappings.processOverElements(new FieldTable.FieldTableElementProcessor()
                 {
-                    String key = en.getKey().toString();
-                    String value = en.getValue().toString();
 
-                    mappingList.add(key + "=" + value);
-                }
+                    public boolean processElement(String propertyName, AMQTypedValue value)
+                    {
+                        mappingList.add(propertyName + "=" + value.getValue());
+                        return true;
+                    }
+
+                    public Object getResult()
+                    {
+                        return mappingList;
+                    }
+                });
+
 
                 Object[] bindingItemValues = {count++, queueName, mappingList.toArray(new String[0])};
                 CompositeData bindingData = new CompositeDataSupport(_bindingDataType, _bindingItemNames, bindingItemValues);
@@ -155,7 +157,7 @@
             }
 
             String[] bindings  = binding.split(",");
-            FieldTable fieldTable = FieldTableFactory.newFieldTable();
+            FieldTable bindingMap = new FieldTable();
             for (int i = 0; i < bindings.length; i++)
             {
                 String[] keyAndValue = bindings[i].split("=");
@@ -163,10 +165,10 @@
                 {
                     throw new JMException("Format for headers binding should be \"<attribute1>=<value1>,<attribute2>=<value2>\" ");
                 }
-                fieldTable.put(keyAndValue[0], keyAndValue[1]);
+                bindingMap.setString(keyAndValue[0], keyAndValue[1]);
             }
 
-            _bindings.add(new Registration(new HeadersBinding(fieldTable), queue));
+            _bindings.add(new Registration(new HeadersBinding(bindingMap), queue));
         }
 
     } // End of MBean class
@@ -185,7 +187,7 @@
 
     public void route(AMQMessage payload) throws AMQException
     {
-        Map headers = getHeaders(payload.getContentHeaderBody());
+        FieldTable headers = getHeaders(payload.getContentHeaderBody());
         if (_logger.isDebugEnabled())
         {
             _logger.debug("Exchange " + getName() + ": routing message with headers " + headers);
@@ -248,7 +250,7 @@
         return !_bindings.isEmpty();
     }
 
-    protected Map getHeaders(ContentHeaderBody contentHeaderFrame)
+    protected FieldTable getHeaders(ContentHeaderBody contentHeaderFrame)
     {
         //what if the content type is not 'basic'? 'file' and 'stream' content classes also define headers,
         //but these are not yet implemented.

Modified: incubator/qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java?view=diff&rev=489748&r1=489747&r2=489748
==============================================================================
--- incubator/qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java (original)
+++ incubator/qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java Fri Dec 22 12:32:43 2006
@@ -24,17 +24,18 @@
 import java.util.HashMap;
 
 import junit.framework.TestCase;
+import org.apache.qpid.framing.FieldTable;
 
 /**
  */
 public class HeadersBindingTest extends TestCase
 {
-    private Map<String, String> bindHeaders = new HashMap<String, String>();
-    private Map<String, String> matchHeaders = new HashMap<String, String>();
+    private FieldTable bindHeaders = new FieldTable();
+    private FieldTable matchHeaders = new FieldTable();
 
     public void testDefault_1()
     {
-        bindHeaders.put("A", "Value of A");
+        bindHeaders.setString("A", "Value of A");
 
         matchHeaders.put("A", "Value of A");
 

Modified: incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java?view=diff&rev=489748&r1=489747&r2=489748
==============================================================================
--- incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java (original)
+++ incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java Fri Dec 22 12:32:43 2006
@@ -986,7 +986,7 @@
                 //    ft.put("headers", rawSelector.getDataAsBytes());
                 if (rawSelector != null)
                 {
-                    ft.putAll(rawSelector);
+                    ft.addAll(rawSelector);
                 }
                 BasicMessageConsumer consumer = new BasicMessageConsumer(_channelId, _connection, amqd, selector, noLocal,
                                                                          _messageFactoryRegistry, AMQSession.this,

Modified: incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java?view=diff&rev=489748&r1=489747&r2=489748
==============================================================================
--- incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java (original)
+++ incubator/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java Fri Dec 22 12:32:43 2006
@@ -452,10 +452,6 @@
         }
     }
 
-    public Map getUnderlyingMessagePropertiesMap()
-    {
-        return getJmsContentHeaderProperties().getHeaders();
-    }
 
     public void setUnderlyingMessagePropertiesMap(FieldTable messageProperties)
     {

Modified: incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/test/unit/message/StreamMessageTest.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/test/unit/message/StreamMessageTest.java?view=diff&rev=489748&r1=489747&r2=489748
==============================================================================
--- incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/test/unit/message/StreamMessageTest.java (original)
+++ incubator/qpid/trunk/qpid/java/client/src/test/java/org/apache/qpid/test/unit/message/StreamMessageTest.java Fri Dec 22 12:32:43 2006
@@ -17,7 +17,6 @@
 import org.apache.qpid.client.transport.TransportConnection;
 import org.apache.qpid.exchange.ExchangeDefaults;
 import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.framing.PropertyFieldTable;
 import org.apache.qpid.url.AMQBindingURL;
 import org.apache.qpid.url.BindingURL;
 
@@ -53,7 +52,7 @@
 
 
         AMQHeadersExchange queue = new AMQHeadersExchange(new AMQBindingURL(ExchangeDefaults.HEADERS_EXCHANGE_CLASS+"://"+ExchangeDefaults.HEADERS_EXCHANGE_NAME+"/test/queue1?"+ BindingURL.OPTION_ROUTING_KEY+"='F0000=1'"));
-        FieldTable ft = new PropertyFieldTable();
+        FieldTable ft = new FieldTable();
         ft.setString("F1000","1");
         MessageConsumer consumer = consumerSession.createConsumer(queue, AMQSession.DEFAULT_PREFETCH_LOW_MARK, AMQSession.DEFAULT_PREFETCH_HIGH_MARK, false, false, (String)null, ft);
 

Added: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQType.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQType.java?view=auto&rev=489748
==============================================================================
--- incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQType.java (added)
+++ incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQType.java Fri Dec 22 12:32:43 2006
@@ -0,0 +1,688 @@
+/*
+ *
+ * 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;
+
+public enum AMQType
+{
+
+
+    //AMQP FieldTable Wire Types
+
+    DECIMAL('D')
+    {
+
+        public int getEncodingSize(Object value)
+        {
+            // TODO : fixme
+            throw new UnsupportedOperationException();
+        }
+
+        public Object toNativeValue(Object value)
+        {
+            // TODO : fixme
+            throw new UnsupportedOperationException();
+        }
+
+        public void writeValueImpl(Object value, ByteBuffer buffer)
+        {
+            // TODO : fixme
+            throw new UnsupportedOperationException();
+        }
+
+        public Object readValueFromBuffer(ByteBuffer buffer)
+        {
+            // TODO : fixme
+            throw new UnsupportedOperationException();
+        }
+    },
+
+    UNSIGNED_SHORT('S')
+    {
+
+        public int getEncodingSize(Object value)
+        {
+            // TODO : fixme
+            throw new UnsupportedOperationException();
+        }
+
+        public Object toNativeValue(Object value)
+        {
+            // TODO : fixme
+            throw new UnsupportedOperationException();
+        }
+
+        public void writeValueImpl(Object value, ByteBuffer buffer)
+        {
+            // TODO : fixme
+            throw new UnsupportedOperationException();
+        }
+
+        public Object readValueFromBuffer(ByteBuffer buffer)
+        {
+            // TODO : fixme
+            throw new UnsupportedOperationException();
+        }
+
+    },
+
+    UNSIGNED_INT('I')
+    {
+
+        public int getEncodingSize(Object value)
+        {
+            // TODO : fixme
+            throw new UnsupportedOperationException();
+        }
+
+
+        public Object toNativeValue(Object value)
+        {
+            // TODO : fixme
+            throw new UnsupportedOperationException();
+        }
+
+        public void writeValueImpl(Object value, ByteBuffer buffer)
+        {
+            // TODO : fixme
+            throw new UnsupportedOperationException();
+        }
+
+        public Object readValueFromBuffer(ByteBuffer buffer)
+        {
+            // TODO : fixme
+            throw new UnsupportedOperationException();
+        }
+    },
+
+    UNSIGNED_LONG('L')
+    {
+
+        public int getEncodingSize(Object value)
+        {
+            // TODO : fixme
+            throw new UnsupportedOperationException();
+        }
+
+
+        public Long toNativeValue(Object value)
+        {
+            // TODO : fixme
+            throw new UnsupportedOperationException();
+        }
+
+        public void writeValueImpl(Object value, ByteBuffer buffer)
+        {
+            // TODO : fixme
+            throw new UnsupportedOperationException();
+        }
+
+        public Object readValueFromBuffer(ByteBuffer buffer)
+        {
+            // TODO : fixme
+            throw new UnsupportedOperationException();
+        }
+    },
+
+    EXTTENDED('D')
+    {
+
+        public int getEncodingSize(Object value)
+        {
+            // TODO : fixme
+            throw new UnsupportedOperationException();
+        }
+
+
+        public Object toNativeValue(Object value)
+        {
+            // TODO : fixme
+            throw new UnsupportedOperationException();
+        }
+
+        public void writeValueImpl(Object value, ByteBuffer buffer)
+        {
+            // TODO : fixme
+            throw new UnsupportedOperationException();
+        }
+
+        public Object readValueFromBuffer(ByteBuffer buffer)
+        {
+            // TODO : fixme
+            throw new UnsupportedOperationException();
+        }
+    },
+
+    TIMESTAMP('T')
+    {
+
+        public int getEncodingSize(Object value)
+        {
+            // TODO : fixme
+            throw new UnsupportedOperationException();
+        }
+
+
+        public Object toNativeValue(Object value)
+        {
+            // TODO : fixme
+            throw new UnsupportedOperationException();
+        }
+
+        public void writeValueImpl(Object value, ByteBuffer buffer)
+        {
+            // TODO : fixme
+            throw new UnsupportedOperationException();
+        }
+
+        public Object readValueFromBuffer(ByteBuffer buffer)
+        {
+            // TODO : fixme
+            throw new UnsupportedOperationException();
+        }
+    },
+
+    BINARY('x')
+    {
+        public int getEncodingSize(Object value)
+        {
+            return 1 + (value == null ? 0 : ((byte[]) value).length);
+        }
+
+
+        public Object toNativeValue(Object value)
+        {
+            if((value instanceof byte[]) || (value == null))
+            {
+                return value;
+            }
+            else
+            {
+                throw new IllegalArgumentException("Value: " + value + " (" + value.getClass().getName() +
+                                                    ") cannot be converted to byte[]");
+            }
+        }
+
+
+        public void writeValueImpl(Object value, ByteBuffer buffer)
+        {
+            EncodingUtils.writeBytes(buffer, (byte[]) value);            
+        }
+
+        public Object readValueFromBuffer(ByteBuffer buffer)
+        {
+            return EncodingUtils.readBytes(buffer);
+        }
+
+    },
+
+    ASCII_STRING('c')
+    {
+        public int getEncodingSize(Object value)
+        {
+            return EncodingUtils.encodedLongStringLength((String) value);
+        }
+
+
+        public String toNativeValue(Object value)
+        {
+            if (value != null)
+            {
+                return value.toString();
+            }
+            else
+            {
+                throw new NullPointerException("Cannot convert: null to String.");
+            }
+        }
+
+        public void writeValueImpl(Object value, ByteBuffer buffer)
+        {
+            EncodingUtils.writeLongStringBytes(buffer, (String) value);
+        }
+
+        public Object readValueFromBuffer(ByteBuffer buffer)
+        {
+            return EncodingUtils.readLongString(buffer);
+        }
+
+    },
+
+    WIDE_STRING('C')
+    {
+        public int getEncodingSize(Object value)
+        {
+            // FIXME: use proper charset encoder
+            return EncodingUtils.encodedLongStringLength((String) value);
+        }
+
+
+        public String toNativeValue(Object value)
+        {
+            if (value != null)
+            {
+                return value.toString();
+            }
+            else
+            {
+                throw new NullPointerException("Cannot convert: null to String.");
+            }
+        }
+
+        public void writeValueImpl(Object value, ByteBuffer buffer)
+        {
+            EncodingUtils.writeLongStringBytes(buffer, (String) value);
+        }
+
+        public Object readValueFromBuffer(ByteBuffer buffer)
+        {
+            return EncodingUtils.readLongString(buffer);
+        }
+    },
+
+    NULL_STRING('n')
+    {
+
+        public int getEncodingSize(Object value)
+        {
+            return 0;
+        }
+
+
+        public String toNativeValue(Object value)
+        {
+            if (value == null)
+            {
+                return null;
+            }
+            else
+            {
+                throw new NumberFormatException("Cannot convert: " + value + "(" +
+                                                value.getClass().getName() + ") to null String.");
+            }
+        }
+
+        public void writeValueImpl(Object value, ByteBuffer buffer)
+        {
+        }
+
+        public Object readValueFromBuffer(ByteBuffer buffer)
+        {
+            return null;
+        }
+    },
+
+    BOOLEAN('t')
+    {
+        public int getEncodingSize(Object value)
+        {
+            return EncodingUtils.encodedBooleanLength();
+        }
+
+
+        public Object toNativeValue(Object value)
+        {
+            if (value instanceof Boolean)
+            {
+                return (Boolean) value;
+            }
+            else if ((value instanceof String) || (value == null))
+            {
+                return Boolean.valueOf((String)value);
+            }
+            else
+            {
+                throw new NumberFormatException("Cannot convert: " + value + "(" +
+                                                value.getClass().getName() + ") to boolean.");
+            }
+        }
+
+        public void writeValueImpl(Object value, ByteBuffer buffer)
+        {
+            EncodingUtils.writeBoolean(buffer, (Boolean) value);
+        }
+
+
+        public Object readValueFromBuffer(ByteBuffer buffer)
+        {
+            return EncodingUtils.readBoolean(buffer);
+        }
+    },
+
+    BYTE('b')
+    {
+        public int getEncodingSize(Object value)
+        {
+            return EncodingUtils.encodedByteLength();
+        }
+
+
+        public Byte toNativeValue(Object value)
+        {
+            if (value instanceof Byte)
+            {
+                return (Byte) value;
+            }
+            else if ((value instanceof String) || (value == null))
+            {
+                return Byte.valueOf((String)value);
+            }
+            else
+            {
+                throw new NumberFormatException("Cannot convert: " + value + "(" +
+                                                value.getClass().getName() + ") to byte.");
+            }
+        }
+
+        public void writeValueImpl(Object value, ByteBuffer buffer)
+        {
+            EncodingUtils.writeByte(buffer, (Byte) value);
+        }
+
+        public Object readValueFromBuffer(ByteBuffer buffer)
+        {
+            return EncodingUtils.readByte(buffer);
+        }
+    },
+
+    ASCII_CHARACTER('k')
+    {
+        public int getEncodingSize(Object value)
+        {
+            return EncodingUtils.encodedCharLength();
+        }
+
+
+        public Character toNativeValue(Object value)
+        {
+            if (value instanceof Character)
+            {
+                return (Character) value;
+            }
+            else if (value == null)
+            {
+                throw new NullPointerException("Cannot convert null into char");
+            }
+            else
+            {
+                throw new NumberFormatException("Cannot convert: " + value + "(" +
+                                                value.getClass().getName() + ") to char.");
+            }
+        }
+
+        public void writeValueImpl(Object value, ByteBuffer buffer)
+        {
+            EncodingUtils.writeChar(buffer, (Character) value);
+        }
+
+        public Object readValueFromBuffer(ByteBuffer buffer)
+        {
+            return EncodingUtils.readChar(buffer);
+        }
+
+    },
+
+    SHORT('s')
+    {
+
+        public int getEncodingSize(Object value)
+        {
+            return EncodingUtils.encodedShortLength();
+        }
+
+
+        public Short toNativeValue(Object value)
+        {
+            if (value instanceof Short)
+            {
+                return (Short) value;
+            }
+            else if (value instanceof Byte)
+            {
+                return ((Byte) value).shortValue();
+            }
+            else if ((value instanceof String) || (value == null))
+            {
+                return Short.valueOf((String)value);
+            }
+
+            else
+            {
+                throw new NumberFormatException("Cannot convert: " + value + "(" +
+                                                value.getClass().getName() + ") to short.");
+            }
+
+
+        }
+
+        public void writeValueImpl(Object value, ByteBuffer buffer)
+        {
+            EncodingUtils.writeShort(buffer, (Short) value);
+        }
+
+        public Object readValueFromBuffer(ByteBuffer buffer)
+        {
+            return EncodingUtils.readShort(buffer);
+        }
+    },
+
+    INT('i')
+    {
+        public int getEncodingSize(Object value)
+        {
+            return EncodingUtils.encodedIntegerLength();
+        }
+
+        public Integer toNativeValue(Object value)
+        {
+            if (value instanceof Integer)
+            {
+                return (Integer) value;
+            }
+            else if (value instanceof Short)
+            {
+                return ((Short) value).intValue();
+            }
+            else if (value instanceof Byte)
+            {
+                return ((Byte) value).intValue();
+            }
+            else if ((value instanceof String) || (value == null))
+            {
+                return Integer.valueOf((String)value);
+            }
+            else
+            {
+                throw new NumberFormatException("Cannot convert: " + value + "(" +
+                                                value.getClass().getName() + ") to int.");
+            }
+        }
+
+        public void writeValueImpl(Object value, ByteBuffer buffer)
+        {
+            EncodingUtils.writeInteger(buffer, (Integer) value);
+        }
+
+        public Object readValueFromBuffer(ByteBuffer buffer)
+        {
+            return EncodingUtils.readInteger(buffer);
+        }
+    },
+
+    LONG('l')
+    {
+
+        public int getEncodingSize(Object value)
+        {
+            return EncodingUtils.encodedLongLength();
+        }
+
+        public Object toNativeValue(Object value)
+        {
+            if(value instanceof Long)
+            {
+                return (Long) value;
+            }
+            else if (value instanceof Integer)
+            {
+                return ((Integer) value).longValue();
+            }
+            else if (value instanceof Short)
+            {
+                return ((Short) value).longValue();
+            }
+            else if (value instanceof Byte)
+            {
+                return ((Byte) value).longValue();
+            }
+            else if ((value instanceof String) || (value == null))
+            {
+                return Long.valueOf((String)value);
+            }
+            else
+            {
+                throw new NumberFormatException("Cannot convert: " + value + "(" +
+                                                value.getClass().getName() + ") to long.");
+            }
+        }
+
+        public void writeValueImpl(Object value, ByteBuffer buffer)
+        {
+            EncodingUtils.writeLong(buffer, (Long) value);
+        }
+
+
+        public Object readValueFromBuffer(ByteBuffer buffer)
+        {
+            return EncodingUtils.readLong(buffer);
+        }
+    },
+
+    FLOAT('f')
+    {
+        public int getEncodingSize(Object value)
+        {
+            return EncodingUtils.encodedFloatLength();
+        }
+
+
+        public Float toNativeValue(Object value)
+        {
+            if (value instanceof Float)
+            {
+                return (Float) value;
+            }
+            else if ((value instanceof String) || (value == null))
+            {
+                return Float.valueOf((String)value);
+            }
+            else
+            {
+                throw new NumberFormatException("Cannot convert: " + value + "(" +
+                                                value.getClass().getName() + ") to float.");
+            }
+        }
+
+        public void writeValueImpl(Object value, ByteBuffer buffer)
+        {
+            EncodingUtils.writeFloat(buffer, (Float) value);
+        }
+
+        public Object readValueFromBuffer(ByteBuffer buffer)
+        {
+            return EncodingUtils.readFloat(buffer);
+        }
+    },
+
+    DOUBLE('d')
+    {
+
+        public int getEncodingSize(Object value)
+        {
+            return EncodingUtils.encodedDoubleLength();
+        }
+
+
+        public Double toNativeValue(Object value)
+        {
+            if (value instanceof Double)
+            {
+                return (Double) value;
+            }
+            else if (value instanceof Float)
+            {
+                return ((Float) value).doubleValue();
+            }
+            else if ((value instanceof String) || (value == null))
+            {
+                return Double.valueOf((String)value);
+            }
+            else
+            {
+                throw new NumberFormatException("Cannot convert: " + value + "(" +
+                                                value.getClass().getName() + ") to double.");
+            }
+        }
+
+        public void writeValueImpl(Object value, ByteBuffer buffer)
+        {
+            EncodingUtils.writeDouble(buffer, (Double) value);
+        }
+
+        public Object readValueFromBuffer(ByteBuffer buffer)
+        {
+            return EncodingUtils.readDouble(buffer);
+        }
+    };
+
+    private final byte _identifier;
+
+    AMQType(char identifier)
+    {
+        _identifier = (byte) identifier;
+    }
+
+    public final byte identifier()
+    {
+        return _identifier;
+    }
+
+
+    public abstract int getEncodingSize(Object value);
+
+    public abstract Object toNativeValue(Object value);
+
+    public AMQTypedValue asTypedValue(Object value)
+    {
+        return new AMQTypedValue(this, toNativeValue(value));
+    }
+
+    public void writeToBuffer(Object value, ByteBuffer buffer)
+    {
+        buffer.put((byte)identifier());
+        writeValueImpl(value, buffer);
+    }
+
+    abstract void writeValueImpl(Object value, ByteBuffer buffer);
+
+    abstract Object readValueFromBuffer(ByteBuffer buffer);
+}

Added: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypeMap.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypeMap.java?view=auto&rev=489748
==============================================================================
--- incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypeMap.java (added)
+++ incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypeMap.java Fri Dec 22 12:32:43 2006
@@ -0,0 +1,43 @@
+/*
+ *
+ * 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 java.util.Map;
+import java.util.HashMap;
+
+public class AMQTypeMap
+{
+    public static Map<Byte, AMQType> _reverseTypeMap = new HashMap<Byte, AMQType>();
+
+    static
+    {
+        for(AMQType type : AMQType.values())
+        {
+            _reverseTypeMap.put(type.identifier(), type);
+        }
+    }
+
+    public static AMQType getType(Byte identifier)
+    {
+        return _reverseTypeMap.get(identifier);
+    }
+
+}

Added: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java?view=auto&rev=489748
==============================================================================
--- incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java (added)
+++ incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQTypedValue.java Fri Dec 22 12:32:43 2006
@@ -0,0 +1,54 @@
+package org.apache.qpid.framing;
+
+import org.apache.mina.common.ByteBuffer;
+
+public class AMQTypedValue
+{
+    private final AMQType _type;
+    private final Object _value;
+
+
+    public AMQTypedValue(AMQType type, Object value)
+    {
+        if(type == null)
+        {
+            throw new NullPointerException("Cannot create a typed value with null type");
+        }
+        _type = type;
+        _value = type.toNativeValue(value);
+    }
+
+    private AMQTypedValue(AMQType type, ByteBuffer buffer)
+    {
+        _type = type;
+        _value = type.readValueFromBuffer( buffer );
+    }
+
+
+    public AMQType getType()
+    {
+        return _type;
+    }
+
+    public Object getValue()
+    {
+        return _value;
+    }
+
+
+    public void writeToBuffer(ByteBuffer buffer)
+    {
+        _type.writeToBuffer(_value,buffer);
+    }
+
+    public int getEncodingSize()
+    {
+        return _type.getEncodingSize(_value);
+    }
+
+    public static AMQTypedValue readFromBuffer(ByteBuffer buffer)
+    {
+        AMQType type = AMQTypeMap.getType(buffer.get());
+        return new AMQTypedValue(type, buffer);
+    }
+}

Modified: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java?view=diff&rev=489748&r1=489747&r2=489748
==============================================================================
--- incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java (original)
+++ incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java Fri Dec 22 12:32:43 2006
@@ -48,6 +48,19 @@
         }
     }
 
+    public static int encodedShortStringLength(AMQShortString s)
+    {
+        if (s == null)
+        {
+            return 1;
+        }
+        else
+        {
+            return (short) (1 + s.length());
+        }
+    }
+
+
     public static int encodedLongStringLength(String s)
     {
         if (s == null)
@@ -88,12 +101,12 @@
     {
         if (table == null)
         {
-            // size is encoded as 4 octets
+            // length is encoded as 4 octets
             return 4;
         }
         else
         {
-            // size of the table plus 4 octets for the size
+            // length of the table plus 4 octets for the length
             return (int) table.getEncodedSize() + 4;
         }
     }
@@ -104,6 +117,20 @@
         return 0;
     }
 
+    public static void writeShortStringBytes(ByteBuffer buffer, AMQShortString s)
+    {
+
+        if (s != null)
+        {
+            writeBytes(buffer, s.getBytes());
+        }
+        else
+        {
+            // really writing out unsigned byte
+            buffer.put((byte) 0);
+        }
+    }
+
     public static void writeShortStringBytes(ByteBuffer buffer, String s)
     {
         if (s != null)
@@ -312,6 +339,24 @@
         return null;
     }
 
+    public static AMQShortString readShortStringAsAMQShortString(ByteBuffer buffer)
+    {
+        short length = buffer.getUnsigned();
+        if (length == 0)
+        {
+            return null;
+        }
+        else
+        {
+            byte[] stringBytes = new byte[length];
+            buffer.get(stringBytes, 0, length);
+
+            return new AMQShortString(stringBytes);
+        }
+    }
+
+
+
     public static String readShortString(ByteBuffer buffer)
     {
         short length = buffer.getUnsigned();
@@ -448,7 +493,7 @@
         byte[] from = new byte[size];
 
         // Is this not the same.
-        //bb.get(from, 0, size);
+        //bb.get(from, 0, length);
         for (int i = 0; i < size; i++)
         {
             from[i] = bb.get(i);

Modified: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java?view=diff&rev=489748&r1=489747&r2=489748
==============================================================================
--- incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java (original)
+++ incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java Fri Dec 22 12:32:43 2006
@@ -1,98 +1,612 @@
 /*
- *  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
+ * 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
  *
- *  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 org.apache.qpid.AMQPInvalidClassException;
 
-import java.util.Map;
-import java.util.Enumeration;
+import java.util.*;
 
-public interface FieldTable extends Map
+//extends FieldTable
+public class FieldTable
 {
-    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);
+    private static final Logger _logger = Logger.getLogger(FieldTable.class);
 
-    public Object setObject(String string, Object object);
+    private LinkedHashMap<String, AMQTypedValue> _properties;
 
-    public boolean isNullStringValue(String name);
+    public FieldTable()
+    {
+        super();
+        _properties = new LinkedHashMap<String, AMQTypedValue>();
+
+    }
+
+
+
+    /**
+     * 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
+    {
+        this();
+        setFromBuffer(buffer, length);
+    }
+
+
+
+    public Boolean getBoolean(String string)
+    {
+        AMQTypedValue value = _properties.get(string);
+        if (value != null && (value.getType() == AMQType.BOOLEAN))
+        {
+            return (Boolean) value.getValue();
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    public Byte getByte(String string)
+    {
+        AMQTypedValue value = _properties.get(string);
+        if (value != null && (value.getType() == AMQType.BYTE))
+        {
+            return (Byte) value.getValue();
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    public Short getShort(String string)
+    {
+        AMQTypedValue value = _properties.get(string);
+        if (value != null && (value.getType() == AMQType.SHORT))
+        {
+            return (Short) value.getValue();
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    public Integer getInteger(String string)
+    {
+        AMQTypedValue value = _properties.get(string);
+        if (value != null && (value.getType() == AMQType.INT))
+        {
+            return (Integer) value.getValue();
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    public Long getLong(String string)
+    {
+        AMQTypedValue value = _properties.get(string);
+        if (value != null && (value.getType() == AMQType.LONG))
+        {
+            return (Long) value.getValue();
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    public Float getFloat(String string)
+    {
+        AMQTypedValue value = _properties.get(string);
+        if (value != null && (value.getType() == AMQType.FLOAT))
+        {
+            return (Float) value.getValue();
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    public Double getDouble(String string)
+    {
+        AMQTypedValue value = _properties.get(string);
+        if (value != null && (value.getType() == AMQType.DOUBLE))
+        {
+            return (Double) value.getValue();
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    public String getString(String string)
+    {
+        AMQTypedValue value = _properties.get(string);
+        if ((value != null) && ((value.getType() == AMQType.WIDE_STRING) ||
+                                (value.getType() == AMQType.ASCII_STRING)))
+        {
+            return (String) value.getValue();
+        }
+
+        else if ((value != null) && (value.getValue() != null) && !(value.getValue() instanceof byte[]))
+        {
+            return String.valueOf(value.getValue());
+        }
+        else
+        {
+            return null;
+        }
+
+    }
+
+    public Character getCharacter(String string)
+    {
+        AMQTypedValue value = _properties.get(string);
+        if (value != null && (value.getType() == AMQType.ASCII_CHARACTER))
+        {
+            return (Character) value.getValue();
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    public byte[] getBytes(String string)
+    {
+        AMQTypedValue value = _properties.get(string);
+        if (value != null && (value.getType() == AMQType.BINARY))
+        {
+            return (byte[]) value.getValue();
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    public Object getObject(String string)
+    {
+        AMQTypedValue value = _properties.get(string);
+        if(value != null)
+        {
+            return value.getValue();
+        }
+        else
+        {
+            return value;
+        }
+
+    }
+
+    // ************  Setters
+
+    public Object setBoolean(String string, boolean b)
+    {
+        checkPropertyName(string);
+        return _properties.put(string, AMQType.BOOLEAN.asTypedValue(b));
+    }
+
+    public Object setByte(String string, byte b)
+    {
+        checkPropertyName(string);
+        return _properties.put(string, AMQType.BYTE.asTypedValue(b));
+    }
+
+    public Object setShort(String string, short i)
+    {
+        checkPropertyName(string);
+        return _properties.put(string, AMQType.SHORT.asTypedValue(i));
+    }
+
+    public Object setInteger(String string, int i)
+    {
+        checkPropertyName(string);
+        return _properties.put(string, AMQType.INT.asTypedValue(i));
+    }
+
+    public Object setLong(String string, long l)
+    {
+        checkPropertyName(string);
+        return _properties.put(string, AMQType.LONG.asTypedValue(l));
+    }
+
+    public Object setFloat(String string, float v)
+    {
+        checkPropertyName(string);
+        return _properties.put(string, AMQType.FLOAT.asTypedValue(v));
+    }
+
+    public Object setDouble(String string, double v)
+    {
+        checkPropertyName(string);
+        return _properties.put(string, AMQType.DOUBLE.asTypedValue(v));
+    }
+
+    public Object setString(String string, String value)
+    {
+        checkPropertyName(string);
+        if (value == null)
+        {
+            return _properties.put(string, AMQType.NULL_STRING.asTypedValue(null));
+        }
+        else
+        {
+            //FIXME: determine string encoding and set either WIDE or ASCII string
+//            if ()
+            {
+                return _properties.put(string, AMQType.WIDE_STRING.asTypedValue(value));
+            }
+//            else
+//            {
+//                return _properties.put(string, AMQType.ASCII_STRING.asTypedValue(value));
+//            }
+        }
+    }
+
+    public Object setChar(String string, char c)
+    {
+        checkPropertyName(string);
+        return _properties.put(string, AMQType.ASCII_CHARACTER.asTypedValue(c));
+    }
+
+    public Object setBytes(String string, byte[] bytes)
+    {
+        checkPropertyName(string);
+        return _properties.put(string, AMQType.BINARY.asTypedValue(bytes));
+    }
+
+    public Object setBytes(String string, byte[] bytes, int start, int length)
+    {
+        checkPropertyName(string);
+        byte[] newBytes = new byte[length];
+        System.arraycopy(bytes,start,newBytes,0,length);
+        return setBytes(string, bytes);
+    }
+
+
+    public Object setObject(String string, Object object)
+    {
+        if (object instanceof Boolean)
+        {
+            return setBoolean(string, (Boolean) object);
+        }
+        else if (object instanceof Byte)
+        {
+            return setByte(string, (Byte) object);
+        }
+        else if (object instanceof Short)
+        {
+            return setShort(string, (Short) object);
+        }
+        else if (object instanceof Integer)
+        {
+            return setInteger(string, (Integer) object);
+        }
+        else if (object instanceof Long)
+        {
+            return setLong(string, (Long) object);
+        }
+        else if (object instanceof Float)
+        {
+            return setFloat(string, (Float) object);
+        }
+        else if (object instanceof Double)
+        {
+            return setDouble(string, (Double) object);
+        }
+        else if (object instanceof String)
+        {
+            return setString(string, (String) object);
+        }
+        else if (object instanceof Character)
+        {
+            return setChar(string, (Character) object);
+        }
+        else if (object instanceof byte[])
+        {
+            return setBytes(string, (byte[]) object);
+        }
+
+        throw new AMQPInvalidClassException("Only Primatives objects allowed Object is:" + object.getClass());
+    }
+
+
+    public boolean isNullStringValue(String name)
+    {
+        AMQTypedValue value = _properties.get(name);
+        return (value != null) && (value.getType() == AMQType.NULL_STRING);
+    }
+
+    // ***** Methods
+
+    public Enumeration getPropertyNames()
+    {
+        return Collections.enumeration(_properties.keySet());
+    }
+
+    public boolean propertyExists(String propertyName)
+    {
+        return itemExists(propertyName);
+    }
+
+    public boolean itemExists(String string)
+    {
+        return _properties.containsKey(string);
+    }
+
+    public String toString()
+    {
+        return _properties.toString();
+    }
+
+
+
+    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)
+    {
+//        AMQP Spec: 4.2.5.5 Field Tables
+//        Guidelines for implementers:
+//           * Field names MUST start with a letter, '$' or '#' and may continue with
+//             letters, '$' or '#', digits, or underlines, to a maximum length of 128
+//             characters.
+//           * The server SHOULD validate field names and upon receiving an invalid
+//             field name, it SHOULD signal a connection exception with reply code
+//             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)
+        {
+            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) == '#'
+              || propertyName.charAt(0) == '_')) // Not official AMQP added for JMS.
+        {
+            throw new IllegalArgumentException("Identifier '" + propertyName + "' does not start with a valid AMQP start character");
+        }
+    }
+
+ 
+    // *************************  Byte Buffer Processing
+
+    public void writeToBuffer(ByteBuffer buffer)
+    {
+        final boolean trace = _logger.isTraceEnabled();
+
+        if (trace)
+        {
+            _logger.trace("FieldTable::writeToBuffer: Writing encoded length of " + getEncodedSize() + "...");
+        }
+
+        EncodingUtils.writeUnsignedInteger(buffer, getEncodedSize());
+
+        putDataInBuffer(buffer);
+    }
+
+    public byte[] getDataAsBytes()
+    {
+        final int encodedSize = (int) getEncodedSize();
+        final ByteBuffer buffer = ByteBuffer.allocate(encodedSize); // FIXME XXX: Is cast a problem?
+
+        putDataInBuffer(buffer);
+
+        final byte[] result = new byte[encodedSize];
+        buffer.flip();
+        buffer.get(result);
+        buffer.release();
+        return result;
+    }
+
+    public long getEncodedSize()
+    {
+        int encodedSize = 0;
+        for(Map.Entry<String,AMQTypedValue> e : _properties.entrySet())
+        {
+            encodedSize += EncodingUtils.encodedShortStringLength(e.getKey());
+            encodedSize++; // the byte for the encoding Type
+            encodedSize += e.getValue().getEncodingSize();
+
+        }
+        return encodedSize;
+    }
+
+    public void addAll(FieldTable fieldTable)
+    {
+        _properties.putAll(fieldTable._properties);
+    }
+
+
+    public static interface FieldTableElementProcessor
+    {
+        public boolean processElement(String propertyName, AMQTypedValue value);
+        public Object getResult();
+    }
+
+    public Object processOverElements(FieldTableElementProcessor processor)
+    {
+        for(Map.Entry<String,AMQTypedValue> e : _properties.entrySet())
+        {
+            boolean result = processor.processElement(e.getKey(), e.getValue());
+            if(!result)
+            {
+                break;
+            }
+        }
+        return processor.getResult();
+    }
+
+
+    public int size()
+    {
+        return _properties.size();
+    }
+
+    public boolean isEmpty()
+    {
+        return _properties.isEmpty();
+    }
+
+    public boolean containsKey(String key)
+    {
+        return _properties.containsKey(key);
+    }
+
+    public Set<String> keys()
+    {
+        return _properties.keySet();
+    }
+
+
+    public Object get(Object key)
+    {
+
+        return getObject((String)key);
+    }
+
+
+    public Object put(Object key, Object value)
+    {
+        return setObject(key.toString(), value);
+    }
+
+    
+    public Object remove(String key)
+    {
+        AMQTypedValue value = _properties.remove(key);
+        return value == null ? null : value.getValue();
+    }
+
+
+
+    public void clear()
+    {
+        _properties.clear();
+    }
+
+    public Set keySet()
+    {
+        return _properties.keySet();
+    }
+
+    private void putDataInBuffer(ByteBuffer buffer)
+    {
+
+        final Iterator<Map.Entry<String,AMQTypedValue>> 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
+
+
+        while (it.hasNext())
+        {
+            final Map.Entry<String,AMQTypedValue> me = it.next();
+            try
+            {
+                if (_logger.isTraceEnabled())
+                {
+                    _logger.trace("Writing Property:" + me.getKey() +
+                                  " Type:" + me.getValue().getType() +
+                                  " Value:" + me.getValue().getValue());
+                    _logger.trace("Buffer Position:" + buffer.position() +
+                                  " Remaining:" + buffer.remaining());
+                }
+
+
+
+                //Write the actual parameter name
+                EncodingUtils.writeShortStringBytes(buffer, me.getKey());
+                me.getValue().writeToBuffer(buffer);
+            }
+            catch (Exception e)
+            {
+                if (_logger.isTraceEnabled())
+                {
+                    _logger.trace("Exception thrown:" + e);
+                    _logger.trace("Writing Property:" + me.getKey() +
+                                  " Type:" + me.getValue().getType() +
+                                  " Value:" + me.getValue().getValue());
+                    _logger.trace("Buffer Position:" + buffer.position() +
+                                  " Remaining:" + buffer.remaining());
+                }
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+
+    public void setFromBuffer(ByteBuffer buffer, long length) throws AMQFrameDecodingException
+    {
+        final boolean trace = _logger.isTraceEnabled();
+
+        int sizeRead = 0;
+        while (sizeRead < length)
+        {
+            int sizeRemaining = buffer.remaining();
+            final String key = EncodingUtils.readShortString(buffer);
+            AMQTypedValue value = AMQTypedValue.readFromBuffer(buffer);
+            sizeRead += (sizeRemaining - buffer.remaining());
+
+            if (trace)
+            {
+                _logger.trace("FieldTable::PropFieldTable(buffer," + length + "): Read type '" + value.getType() + "', key '" + key + "', value '" + value.getValue() + "' (now read " + sizeRead + " of " + length + " encoded bytes)...");
+            }
+
+            _properties.put(key,value);
+        }
+
+        if (trace)
+        {
+            _logger.trace("FieldTable::FieldTable(buffer," + length + "): Done.");
+        }
+    }
 
 }

Modified: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/FieldTableFactory.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/FieldTableFactory.java?view=diff&rev=489748&r1=489747&r2=489748
==============================================================================
--- incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/FieldTableFactory.java (original)
+++ incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/FieldTableFactory.java Fri Dec 22 12:32:43 2006
@@ -26,16 +26,13 @@
 {
     public static FieldTable newFieldTable()
     {
-        return new PropertyFieldTable();
+        return new FieldTable();
     }
 
     public static FieldTable newFieldTable(ByteBuffer byteBuffer, long length) throws AMQFrameDecodingException
     {
-        return new PropertyFieldTable(byteBuffer, length);
+        return new FieldTable(byteBuffer, length);
     }
 
-    public static FieldTable newFieldTable(String text)
-    {
-        return new PropertyFieldTable(text);
-    }
+
 }

Modified: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/JMSPropertyFieldTable.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/JMSPropertyFieldTable.java?view=diff&rev=489748&r1=489747&r2=489748
==============================================================================
--- incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/JMSPropertyFieldTable.java (original)
+++ incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/framing/JMSPropertyFieldTable.java Fri Dec 22 12:32:43 2006
@@ -32,29 +32,11 @@
 {
     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)
     {

Modified: incubator/qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/framing/BasicContentHeaderPropertiesTest.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/framing/BasicContentHeaderPropertiesTest.java?view=diff&rev=489748&r1=489747&r2=489748
==============================================================================
--- incubator/qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/framing/BasicContentHeaderPropertiesTest.java (original)
+++ incubator/qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/framing/BasicContentHeaderPropertiesTest.java Fri Dec 22 12:32:43 2006
@@ -31,7 +31,7 @@
 {
 
     BasicContentHeaderProperties _testProperties;
-    PropertyFieldTable _testTable;
+    FieldTable _testTable;
     String _testString = "This is a test string";
     int _testint = 666;
 
@@ -45,11 +45,9 @@
 
     public void setUp()
     {
-        HashMap _testMap = new HashMap(10);
-        _testMap.put("TestString", _testString);
-        _testMap.put("Testint", _testint);
-        _testTable = new PropertyFieldTable();
-        _testTable.putAll(_testMap);
+        _testTable = new FieldTable();
+        _testTable.setString("TestString", _testString);
+        _testTable.setInteger("Testint", _testint);
         _testProperties = new BasicContentHeaderProperties();
         _testProperties.setHeaders(_testTable);
     }
@@ -57,7 +55,7 @@
     public void testGetPropertyListSize()
     {
         //needs a better test but at least we're exercising the code !
-         // FT size is encoded in an int
+         // FT length is encoded in an int
         int expectedSize = EncodingUtils.encodedIntegerLength();
 
         expectedSize += EncodingUtils.encodedShortStringLength("TestInt");

Modified: incubator/qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/framing/JMSPropertyFieldTableTest.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/framing/JMSPropertyFieldTableTest.java?view=diff&rev=489748&r1=489747&r2=489748
==============================================================================
--- incubator/qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/framing/JMSPropertyFieldTableTest.java (original)
+++ incubator/qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/framing/JMSPropertyFieldTableTest.java Fri Dec 22 12:32:43 2006
@@ -51,7 +51,7 @@
      */
     public void testReplacement() throws JMSException
     {
-        JMSPropertyFieldTable table1 = new JMSPropertyFieldTable();
+        JMSPropertyFieldTable table1 = new JMSPropertyFieldTable(new FieldTable());
         //Set a boolean value
         table1.setBoolean("value", true);
 
@@ -73,7 +73,7 @@
 
     public void testRemoval() throws JMSException
     {
-        JMSPropertyFieldTable table1 = new JMSPropertyFieldTable();
+        JMSPropertyFieldTable table1 = new JMSPropertyFieldTable(new FieldTable());
         //Set a boolean value
         table1.setBoolean("value", true);
 
@@ -99,7 +99,7 @@
      */
     public void testBoolean() throws JMSException
     {
-        JMSPropertyFieldTable table1 = new JMSPropertyFieldTable();
+        JMSPropertyFieldTable table1 = new JMSPropertyFieldTable(new FieldTable());
         table1.setBoolean("value", true);
         Assert.assertTrue(table1.propertyExists("value"));
 
@@ -184,7 +184,7 @@
         //but after a remove it doesn't
         Assert.assertFalse(table1.propertyExists("value"));
 
-        // Table should now have zero size for encoding
+        // Table should now have zero length for encoding
         checkEmpty(table1);
 
         //Looking up an invalid value will return false
@@ -197,7 +197,7 @@
      */
     public void testByte() throws JMSException
     {
-        JMSPropertyFieldTable table1 = new JMSPropertyFieldTable();
+        JMSPropertyFieldTable table1 = new JMSPropertyFieldTable(new FieldTable());
         table1.setByte("value", Byte.MAX_VALUE);
         Assert.assertTrue(table1.propertyExists("value"));
 
@@ -243,7 +243,7 @@
         //but after a remove it doesn't
         Assert.assertFalse(table1.propertyExists("value"));
 
-        // Table should now have zero size for encoding
+        // Table should now have zero length for encoding
         checkEmpty(table1);
 
         //Looking up an invalid value returns null
@@ -266,7 +266,7 @@
      */
     public void testShort() throws JMSException
     {
-        JMSPropertyFieldTable table1 = new JMSPropertyFieldTable();
+        JMSPropertyFieldTable table1 = new JMSPropertyFieldTable(new FieldTable());
         table1.setShort("value", Short.MAX_VALUE);
         Assert.assertTrue(table1.propertyExists("value"));
 
@@ -323,7 +323,7 @@
         //but after a remove it doesn't
         Assert.assertFalse(table1.propertyExists("value"));
 
-        // Table should now have zero size for encoding
+        // Table should now have zero length for encoding
         checkEmpty(table1);
 
         //Looking up an invalid value returns null
@@ -345,7 +345,7 @@
      */
     public void testDouble() throws JMSException
     {
-        JMSPropertyFieldTable table1 = new JMSPropertyFieldTable();
+        JMSPropertyFieldTable table1 = new JMSPropertyFieldTable(new FieldTable());
         table1.setDouble("value", Double.MAX_VALUE);
         Assert.assertTrue(table1.propertyExists("value"));
 
@@ -414,7 +414,7 @@
         //but after a remove it doesn't
         Assert.assertFalse(table1.propertyExists("value"));
 
-        // Table should now have zero size for encoding
+        // Table should now have zero length for encoding
         checkEmpty(table1);
 
         //Looking up an invalid value returns null
@@ -437,7 +437,7 @@
      */
     public void testFloat() throws JMSException
     {
-        JMSPropertyFieldTable table1 = new JMSPropertyFieldTable();
+        JMSPropertyFieldTable table1 = new JMSPropertyFieldTable(new FieldTable());
         table1.setFloat("value", Float.MAX_VALUE);
         Assert.assertTrue(table1.propertyExists("value"));
 
@@ -500,7 +500,7 @@
         //but after a remove it doesn't
         Assert.assertFalse(table1.propertyExists("value"));
 
-        // Table should now have zero size for encoding
+        // Table should now have zero length for encoding
         checkEmpty(table1);
 
         //Looking up an invalid value returns null
@@ -522,7 +522,7 @@
      */
     public void testInt() throws JMSException
     {
-        JMSPropertyFieldTable table1 = new JMSPropertyFieldTable();
+        JMSPropertyFieldTable table1 = new JMSPropertyFieldTable(new FieldTable());
         table1.setInteger("value", Integer.MAX_VALUE);
         Assert.assertTrue(table1.propertyExists("value"));
 
@@ -586,7 +586,7 @@
         //but after a remove it doesn't
         Assert.assertFalse(table1.propertyExists("value"));
 
-        // Table should now have zero size for encoding
+        // Table should now have zero length for encoding
         checkEmpty(table1);
 
         //Looking up an invalid value returns null
@@ -608,7 +608,7 @@
      */
     public void testLong() throws JMSException
     {
-        JMSPropertyFieldTable table1 = new JMSPropertyFieldTable();
+        JMSPropertyFieldTable table1 = new JMSPropertyFieldTable(new FieldTable());
         table1.setLong("value", Long.MAX_VALUE);
         Assert.assertTrue(table1.propertyExists("value"));
 
@@ -679,7 +679,7 @@
         //but after a remove it doesn't
         Assert.assertFalse(table1.propertyExists("value"));
 
-        // Table should now have zero size for encoding
+        // Table should now have zero length for encoding
         checkEmpty(table1);
 
         //Looking up an invalid value
@@ -700,7 +700,7 @@
      * Calls all methods that can be used to check the table is empty
      * - getEncodedSize
      * - isEmpty
-     * - size
+     * - length
      *
      * @param table to check is empty
      */
@@ -716,7 +716,7 @@
      */
     public void testString() throws JMSException
     {
-        JMSPropertyFieldTable table1 = new JMSPropertyFieldTable();
+        JMSPropertyFieldTable table1 = new JMSPropertyFieldTable(new FieldTable());
         table1.setString("value", "Hello");
         Assert.assertTrue(table1.propertyExists("value"));
 
@@ -799,7 +799,7 @@
 
     public void testValues() throws JMSException
     {
-        JMSPropertyFieldTable table = new JMSPropertyFieldTable();
+        JMSPropertyFieldTable table = new JMSPropertyFieldTable(new FieldTable());
         table.setBoolean("bool", true);
         table.setDouble("double", Double.MAX_VALUE);
         table.setFloat("float", Float.MAX_VALUE);
@@ -842,7 +842,7 @@
      */
     public void testCheckPropertyNameasNull() throws JMSException
     {
-        JMSPropertyFieldTable table = new JMSPropertyFieldTable();
+        JMSPropertyFieldTable table = new JMSPropertyFieldTable(new FieldTable());
 
         try
         {
@@ -862,7 +862,7 @@
      */
     public void testCheckPropertyNameasEmptyString() throws JMSException
     {
-        JMSPropertyFieldTable table = new JMSPropertyFieldTable();
+        JMSPropertyFieldTable table = new JMSPropertyFieldTable(new FieldTable());
 
         try
         {
@@ -882,7 +882,7 @@
      */
     public void testCheckPropertyNamehasMaxLength() throws JMSException
     {
-        JMSPropertyFieldTable table = new JMSPropertyFieldTable();
+        JMSPropertyFieldTable table = new JMSPropertyFieldTable(new FieldTable());
 
         StringBuffer longPropertyName = new StringBuffer(129);
 
@@ -910,7 +910,7 @@
      */
     public void testCheckPropertyNameStartCharacterIsLetter() throws JMSException
     {
-        JMSPropertyFieldTable table = new JMSPropertyFieldTable();
+        JMSPropertyFieldTable table = new JMSPropertyFieldTable(new FieldTable());
 
         //Try a name that starts with a number
         try
@@ -931,7 +931,7 @@
      */
     public void testCheckPropertyNameContainsInvalidCharacter() throws JMSException
     {
-        JMSPropertyFieldTable table = new JMSPropertyFieldTable();
+        JMSPropertyFieldTable table = new JMSPropertyFieldTable(new FieldTable());
 
         //Try a name that starts with a number
         try
@@ -953,7 +953,7 @@
      */
     public void testCheckPropertyNameIsInvalid() throws JMSException
     {
-        JMSPropertyFieldTable table = new JMSPropertyFieldTable();
+        JMSPropertyFieldTable table = new JMSPropertyFieldTable(new FieldTable());
 
         //Try a name that starts with a number
         try
@@ -995,7 +995,7 @@
     public void testSets()
     {
 
-        JMSPropertyFieldTable table = new JMSPropertyFieldTable();
+        JMSPropertyFieldTable table = new JMSPropertyFieldTable(new FieldTable());
 
         table.put("n1", "1");
         table.put("n2", "2");