Author: jochen
Date: Thu Nov 23 14:21:42 2006
New Revision: 478685

URL: http://svn.apache.org/viewvc?view=rev&rev=478685
Log:
It is now possible, to have other objects than strings as
map keys, if extensions are enabled.

Modified:
    
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/parser/MapParser.java
    
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/serializer/MapSerializer.java
    webservices/xmlrpc/trunk/pom.xml
    webservices/xmlrpc/trunk/src/changes/changes.xml
    
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/SerializerTest.java

Modified: 
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/parser/MapParser.java
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/parser/MapParser.java?view=diff&rev=478685&r1=478684&r2=478685
==============================================================================
--- 
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/parser/MapParser.java
 (original)
+++ 
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/parser/MapParser.java
 Thu Nov 23 14:21:42 2006
@@ -35,7 +35,8 @@
  */
 public class MapParser extends RecursiveTypeParserImpl {
        private int level = 0;
-       private String name;
+       private StringBuffer nameBuffer = new StringBuffer();
+    private Object nameObject;
        private Map map;
        private boolean inName, inValue, doneValue;
 
@@ -51,17 +52,21 @@
        }
 
        protected void addResult(Object pResult) throws SAXException {
-               if (name == null) {
-                       throw new SAXParseException("Invalid state: Expected 
name",
-                                                                               
getDocumentLocator());
-               } else {
-                       if (map.containsKey(name)) {
-                               throw new SAXParseException("Duplicate name: " 
+ name,
-                                                                               
        getDocumentLocator());
-                       } else {
-                               map.put(name, pResult);
-                       }
-               }
+           if (inName) {
+               nameObject = pResult;
+        } else {
+            if (nameObject == null) {
+                       throw new SAXParseException("Invalid state: Expected 
name",
+                                                                               
getDocumentLocator());
+               } else {
+                       if (map.containsKey(nameObject)) {
+                               throw new SAXParseException("Duplicate name: " 
+ nameObject,
+                                                                               
        getDocumentLocator());
+                       } else {
+                               map.put(nameObject, pResult);
+                       }
+               }
+        }
        }
 
        public void startDocument() throws SAXException {
@@ -72,9 +77,8 @@
        }
 
        public void characters(char[] pChars, int pOffset, int pLength) throws 
SAXException {
-               if (inName) {
-                       String s = new String(pChars, pOffset, pLength);
-                       name = name == null ? s : name + s;
+               if (inName  &&  !inValue) {
+            nameBuffer.append(pChars, pOffset, pLength);
                } else {
                        super.characters(pChars, pOffset, pLength);
                }
@@ -105,7 +109,8 @@
                                                                                
                getDocumentLocator());
                                }
                                doneValue = inName = inValue = false;
-                               name = null;
+                nameObject = null;
+                nameBuffer.setLength(0);
                                break;
                        case 2:
                                if (doneValue) {
@@ -114,7 +119,7 @@
                                                                                
                getDocumentLocator());
                                }
                                if ("".equals(pURI)  &&  
MapSerializer.NAME_TAG.equals(pLocalName)) {
-                                       if (name == null) {
+                                       if (nameObject == null) {
                                                inName = true;
                                        } else {
                                                throw new 
SAXParseException("Expected " + TypeSerializerImpl.VALUE_TAG
@@ -122,7 +127,7 @@
                                                                                
                        getDocumentLocator());
                                        }
                                } else if ("".equals(pURI)  &&  
TypeSerializerImpl.VALUE_TAG.equals(pLocalName)) {
-                                       if (name == null) {
+                                       if (nameObject == null) {
                                                throw new 
SAXParseException("Expected " + MapSerializer.NAME_TAG
                                                                                
                        + ", got " + new QName(pURI, pLocalName),
                                                                                
                        getDocumentLocator());
@@ -133,6 +138,20 @@
                                        
                                }
                                break;
+            case 3:
+                if (inName  &&  "".equals(pURI)  &&  
TypeSerializerImpl.VALUE_TAG.equals(pLocalName)) {
+                    if (cfg.isEnabledForExtensions()) {
+                        inValue = true;
+                        startValueTag();
+                    } else {
+                        throw new SAXParseException("Expected /" + 
MapSerializer.NAME_TAG
+                                + ", got " + new QName(pURI, pLocalName),
+                                getDocumentLocator());
+                    }
+                } else {
+                    super.startElement(pURI, pLocalName, pQName, pAttrs);
+                }
+                break;
                        default:
                                super.startElement(pURI, pLocalName, pQName, 
pAttrs);
                                break;
@@ -149,11 +168,28 @@
                        case 2:
                                if (inName) {
                                        inName = false;
-                               } else if (inValue) {
+                                       if (nameObject == null) {
+                                           nameObject = nameBuffer.toString();
+                    } else {
+                        for (int i = 0;  i < nameBuffer.length();  i++) {
+                            if (!Character.isWhitespace(nameBuffer.charAt(i))) 
{
+                                throw new SAXParseException("Unexpected 
non-whitespace character in member name",
+                                        getDocumentLocator());
+                            }
+                        }
+                    }
+                } else if (inValue) {
                                        endValueTag();
                                        doneValue = true;
                                }
                                break;
+            case 3:
+                if (inName  &&  inValue  &&  "".equals(pURI)  &&  
TypeSerializerImpl.VALUE_TAG.equals(pLocalName)) {
+                    endValueTag();
+                } else {
+                    super.endElement(pURI, pLocalName, pQName);
+                }
+                break;
                        default:
                                super.endElement(pURI, pLocalName, pQName);
                }

Modified: 
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/serializer/MapSerializer.java
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/serializer/MapSerializer.java?view=diff&rev=478685&r1=478684&r2=478685
==============================================================================
--- 
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/serializer/MapSerializer.java
 (original)
+++ 
webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/serializer/MapSerializer.java
 Thu Nov 23 14:21:42 2006
@@ -27,18 +27,22 @@
 /** A [EMAIL PROTECTED] TypeSerializer} for maps.
  */
 public class MapSerializer extends TypeSerializerImpl {
-       private final XmlRpcStreamConfig config;
+    /** Tag name of a maps struct tag.
+     */
+    public static final String STRUCT_TAG = "struct";
+
+    /** Tag name of a maps member tag.
+     */
+    public static final String MEMBER_TAG = "member";
+
+    /** Tag name of a maps members name tag.
+     */
+    public static final String NAME_TAG = "name";
+
+    private final XmlRpcStreamConfig config;
        private final TypeFactory typeFactory;
-       /** Tag name of a maps struct tag.
-        */
-       public static final String STRUCT_TAG = "struct";
-       /** Tag name of a maps member tag.
-        */
-       public static final String MEMBER_TAG = "member";
-       /** Tag name of a maps members name tag.
-        */
-       public static final String NAME_TAG = "name";
-       /** Creates a new instance.
+
+    /** Creates a new instance.
         * @param pTypeFactory The factory being used for creating serializers.
         * @param pConfig The configuration being used for creating serializers.
         */
@@ -46,30 +50,43 @@
                typeFactory = pTypeFactory;
                config = pConfig;
        }
-       protected void writeEntry(ContentHandler pHandler, String pKey, Object 
pValue) throws SAXException {
+
+    protected void writeEntry(ContentHandler pHandler, Object pKey, Object 
pValue) throws SAXException {
                pHandler.startElement("", MEMBER_TAG, MEMBER_TAG, 
ZERO_ATTRIBUTES);
                pHandler.startElement("", NAME_TAG, NAME_TAG, ZERO_ATTRIBUTES);
-               pHandler.characters(pKey.toCharArray(), 0, pKey.length());
+               if (config.isEnabledForExtensions()  &&  !(pKey instanceof 
String)) {
+                   writeValue(pHandler, pKey);
+        } else {
+            String key = pKey.toString();
+            pHandler.characters(key.toCharArray(), 0, key.length());
+        }
                pHandler.endElement("", NAME_TAG, NAME_TAG);
-               TypeSerializer ts = typeFactory.getSerializer(config, pValue);
+               writeValue(pHandler, pValue);
+               pHandler.endElement("", MEMBER_TAG, MEMBER_TAG);
+       }
+
+    private void writeValue(ContentHandler pHandler, Object pValue)
+            throws SAXException {
+        TypeSerializer ts = typeFactory.getSerializer(config, pValue);
                if (ts == null) {
                        throw new SAXException("Unsupported Java type: " + 
pValue.getClass().getName());
                }
                ts.write(pHandler, pValue);
-               pHandler.endElement("", MEMBER_TAG, MEMBER_TAG);
-       }
-       protected void writeData(ContentHandler pHandler, Object pData) throws 
SAXException {
+    }
+
+    protected void writeData(ContentHandler pHandler, Object pData) throws 
SAXException {
                Map map = (Map) pData;
                for (Iterator iter = map.entrySet().iterator();  
iter.hasNext();  ) {
                        Map.Entry entry = (Map.Entry) iter.next();
-                       writeEntry(pHandler, entry.getKey().toString(), 
entry.getValue());
+                       writeEntry(pHandler, entry.getKey(), entry.getValue());
                }
        }
-       public void write(final ContentHandler pHandler, Object pObject) throws 
SAXException {
+
+    public void write(final ContentHandler pHandler, Object pObject) throws 
SAXException {
                pHandler.startElement("", VALUE_TAG, VALUE_TAG, 
ZERO_ATTRIBUTES);
                pHandler.startElement("", STRUCT_TAG, STRUCT_TAG, 
ZERO_ATTRIBUTES);
                writeData(pHandler, pObject);
                pHandler.endElement("", STRUCT_TAG, STRUCT_TAG);
                pHandler.endElement("", VALUE_TAG, VALUE_TAG);
        }
-}
\ No newline at end of file
+}

Modified: webservices/xmlrpc/trunk/pom.xml
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/pom.xml?view=diff&rev=478685&r1=478684&r2=478685
==============================================================================
--- webservices/xmlrpc/trunk/pom.xml (original)
+++ webservices/xmlrpc/trunk/pom.xml Thu Nov 23 14:21:42 2006
@@ -314,12 +314,12 @@
                <repository>
                        <id>apache.releases</id>
                        <name>Apache Release Distribution Repository</name>
-                       
<url>scpexe://people.apache.org/www/people.apache.org/repo/m2-ibiblio-rsync-repository</url>
+                       
<url>scp://people.apache.org/www/people.apache.org/repo/m2-ibiblio-rsync-repository</url>
                </repository>
                <snapshotRepository>
                        <id>apache.snapshots</id>
                        <name>Apache Development Snapshot Repository</name>
-                       
<url>scpexe://people.apache.org/www/people.apache.org/repo/m2-snapshot-repository</url>
+                       
<url>scp://people.apache.org/www/people.apache.org/repo/m2-snapshot-repository</url>
                </snapshotRepository>
 
         <site>

Modified: webservices/xmlrpc/trunk/src/changes/changes.xml
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/src/changes/changes.xml?view=diff&rev=478685&r1=478684&r2=478685
==============================================================================
--- webservices/xmlrpc/trunk/src/changes/changes.xml (original)
+++ webservices/xmlrpc/trunk/src/changes/changes.xml Thu Nov 23 14:21:42 2006
@@ -44,6 +44,10 @@
         The ClientFactory is now able to use a custom name for the remote
         handler. So far, it was always using the interface name.
       </action>
+      <action dev="jochen" type="add" issue="XMLRPC-127">
+        It is now possible to have other objects than strings as
+        map keys.
+      </action>
     </release>
     <release version="3.0.1-SNAPSHOT" date="Not yet released">
       <action dev="jochen" type="fix">

Modified: 
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/SerializerTest.java
URL: 
http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/SerializerTest.java?view=diff&rev=478685&r1=478684&r2=478685
==============================================================================
--- 
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/SerializerTest.java
 (original)
+++ 
webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/SerializerTest.java
 Thu Nov 23 14:21:42 2006
@@ -15,11 +15,15 @@
  */
 package org.apache.xmlrpc.test;
 
+import java.io.StringReader;
 import java.util.Calendar;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.TimeZone;
 
+import javax.xml.parsers.SAXParserFactory;
+
 import junit.framework.TestCase;
 
 import org.apache.xmlrpc.XmlRpcRequest;
@@ -28,8 +32,14 @@
 import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
 import org.apache.xmlrpc.client.XmlRpcClientRequestImpl;
 import org.apache.xmlrpc.client.XmlRpcSunHttpTransportFactory;
+import org.apache.xmlrpc.common.TypeFactoryImpl;
 import org.apache.xmlrpc.common.XmlRpcStreamRequestConfig;
+import org.apache.xmlrpc.parser.XmlRpcRequestParser;
+import org.apache.xmlrpc.server.XmlRpcServer;
+import org.apache.xmlrpc.server.XmlRpcServerConfigImpl;
+import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
 
 
 /** A test case for the various serializers.
@@ -146,5 +156,45 @@
             + 
"<param><value><dateTime.iso8601>19330612T11:07:21</dateTime.iso8601></value></param>"
             + "</params></methodCall>";
         assertEquals(expect, got);
+    }
+
+    /**
+     * Test for XMLRPC-127: Is it possible to transmit a
+     * map with integers as the keys?
+     */
+    public void testIntegerKeyMap() throws Exception {
+        Map map = new HashMap();
+        map.put(new Integer(1), "one");
+        XmlRpcStreamRequestConfig config = getExConfig();
+        XmlRpcRequest request = new XmlRpcClientRequestImpl(config, 
"integerKeyMap", new Object[]{map});
+        String got = writeRequest(config, request);
+        String expect =
+            "<?xml version=\"1.0\" encoding=\"US-ASCII\"?>"
+            + "<methodCall 
xmlns:ex=\"http://ws.apache.org/xmlrpc/namespaces/extensions\";>"
+            + "<methodName>integerKeyMap</methodName><params>"
+            + "<param><value><struct><member>"
+            +   "<name><value><i4>1</i4></value></name>"
+            +   "<value>one</value></member>"
+            + "</struct></value></param>"
+            + "</params></methodCall>";
+        assertEquals(expect, got);
+
+        XmlRpcServer server = new XmlRpcServer();
+        XmlRpcServerConfigImpl serverConfig = new XmlRpcServerConfigImpl();
+        serverConfig.setEnabledForExtensions(true);
+        server.setConfig(serverConfig);
+        XmlRpcRequestParser parser = new XmlRpcRequestParser(serverConfig, new 
TypeFactoryImpl(server));
+        SAXParserFactory spf = SAXParserFactory.newInstance();
+        spf.setValidating(false);
+        spf.setNamespaceAware(true);
+        XMLReader xr = spf.newSAXParser().getXMLReader();
+        xr.setContentHandler(parser);
+        xr.parse(new InputSource(new StringReader(expect)));
+        assertEquals("integerKeyMap", parser.getMethodName());
+        List params = parser.getParams();
+        assertEquals(1, params.size());
+        Map paramMap = (Map) params.get(0);
+        assertEquals(1, paramMap.size());
+        assertEquals("one", paramMap.get(new Integer(1)));
     }
 }


Reply via email to