You are viewing a plain text version of this content. The canonical link for it is here.
Posted to xmlrpc-auto@ws.apache.org by jo...@apache.org on 2006/11/23 23:21:42 UTC

svn commit: r478685 - in /webservices/xmlrpc/trunk: ./ common/src/main/java/org/apache/xmlrpc/parser/ common/src/main/java/org/apache/xmlrpc/serializer/ src/changes/ tests/src/test/java/org/apache/xmlrpc/test/

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 {@link 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)));
     }
 }