Henri Gomez wrote:

> Upward compatibility with what ?

With existing XML-RPC code. Attached you find a proposed patch, which
converts calendar values into date objects on the fly, if required. Please
verify, whether it suits you.

Note, that I have fixed the bug with the added timezone information. (You'll
need a new version of ws-commons-util.)


Jochen

Index: /home/jwi/workspace/ws-xmlrpc/client/src/main/java/org/apache/xmlrpc/client/XmlRpcLocalTransport.java
===================================================================
--- /home/jwi/workspace/ws-xmlrpc/client/src/main/java/org/apache/xmlrpc/client/XmlRpcLocalTransport.java	(revision 407079)
+++ /home/jwi/workspace/ws-xmlrpc/client/src/main/java/org/apache/xmlrpc/client/XmlRpcLocalTransport.java	(working copy)
@@ -15,6 +15,8 @@
  */
 package org.apache.xmlrpc.client;
 
+import java.util.Calendar;
+import java.util.Date;
 import java.util.Iterator;
 import java.util.Map;
 
@@ -55,6 +57,8 @@
 			return false;
 		} else {
 			return !(pObject instanceof Integer
+                     ||  pObject instanceof Calendar
+                     ||  pObject instanceof Date
 					 ||  pObject instanceof String
 					 ||  pObject instanceof byte[]
 					 ||  pObject instanceof Double);
Index: /home/jwi/workspace/ws-xmlrpc/common/src/main/java/org/apache/xmlrpc/common/TypeFactoryImpl.java
===================================================================
--- /home/jwi/workspace/ws-xmlrpc/common/src/main/java/org/apache/xmlrpc/common/TypeFactoryImpl.java	(revision 407079)
+++ /home/jwi/workspace/ws-xmlrpc/common/src/main/java/org/apache/xmlrpc/common/TypeFactoryImpl.java	(working copy)
@@ -18,6 +18,7 @@
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.math.BigInteger;
+import java.util.Calendar;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
@@ -140,9 +141,11 @@
 			}
 		} else if (pObject instanceof Double) {
 			return DOUBLE_SERIALIZER;
-		} else if (pObject instanceof Date) {
+		} else if (pObject instanceof Calendar) {
 			return DATE_SERIALIZER;
-		} else if (pObject instanceof byte[]) {
+        } else if (pObject instanceof Date) {
+            return DATE_SERIALIZER;
+    	} else if (pObject instanceof byte[]) {
 			return new ByteArraySerializer();
 		} else if (pObject instanceof Object[]) {
 			return new ObjectArraySerializer(this, pConfig);
Index: /home/jwi/workspace/ws-xmlrpc/server/src/main/java/org/apache/xmlrpc/server/ReflectiveXmlRpcHandler.java
===================================================================
--- /home/jwi/workspace/ws-xmlrpc/server/src/main/java/org/apache/xmlrpc/server/ReflectiveXmlRpcHandler.java	(revision 407079)
+++ /home/jwi/workspace/ws-xmlrpc/server/src/main/java/org/apache/xmlrpc/server/ReflectiveXmlRpcHandler.java	(working copy)
@@ -17,6 +17,8 @@
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.Calendar;
+import java.util.Date;
 
 import org.apache.xmlrpc.XmlRpcException;
 import org.apache.xmlrpc.XmlRpcHandler;
@@ -32,6 +34,7 @@
 	private final Class clazz;
 	private final Object instance;
 	private final Method method;
+    private final boolean converting;
 
 	/** Creates a new instance.
 	 * @param pMapping The mapping, which creates this handler.
@@ -50,6 +53,7 @@
 		clazz = pClass;
 		instance = pInstance;
 		method = pMethod;
+        converting = isConverting(pMethod);
 	}
 
 	public Object execute(XmlRpcRequest pRequest) throws XmlRpcException {
@@ -59,7 +63,8 @@
 	    }
 	    Object[] args = new Object[pRequest.getParameterCount()];
 	    for (int j = 0;  j < args.length;  j++) {
-	        args[j] = pRequest.getParameter(j);
+            Object o = pRequest.getParameter(j);
+	        args[j] = converting ? getConvertedParameter(o, j) : o;
 	    }
 	    try {
 	        return method.invoke(instance, args);
@@ -78,5 +83,33 @@
 	                                  + clazz.getName() + ": "
 	                                  + t.getMessage(), t);
 	    }
-	}
-}
\ No newline at end of file
+    }
+
+	private static boolean isConverting(Method pMethod) {
+	    Class[] params = pMethod.getParameterTypes();
+        for (int i = 0;  i < params.length;  i++) {
+            if (params[i].equals(Date.class)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+	private Object getConvertedParameter(Object pValue, int pOffset) {
+	    Class paramClass = method.getParameterTypes()[pOffset];
+        if (paramClass.equals(Date.class)) {
+            if (pValue == null) {
+                return null;
+            }
+            if (pValue instanceof Calendar) {
+                return ((Calendar) pValue).getTime();
+            }
+            if (pValue instanceof Date) {
+                return pValue;
+            }
+            throw new IllegalStateException("Invalid parameter type: "
+                    + pValue.getClass().getName());
+        }
+        return pValue;
+    }
+}
Index: /home/jwi/workspace/ws-xmlrpc/tests/src/test/java/org/apache/xmlrpc/test/BaseTest.java
===================================================================
--- /home/jwi/workspace/ws-xmlrpc/tests/src/test/java/org/apache/xmlrpc/test/BaseTest.java	(revision 407079)
+++ /home/jwi/workspace/ws-xmlrpc/tests/src/test/java/org/apache/xmlrpc/test/BaseTest.java	(working copy)
@@ -16,9 +16,11 @@
 package org.apache.xmlrpc.test;
 
 import java.io.IOException;
+import java.io.Serializable;
 import java.io.StringReader;
 import java.util.Arrays;
 import java.util.Calendar;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
@@ -260,14 +262,44 @@
 			}
 		}
 
-		/** Returns the calendar value in milliseconds.
+		/** Example of a Serializable instance.
+		 */
+        public static class CalendarWrapper implements Serializable {
+            private static final long serialVersionUID = 8153663910532549627L;
+            final Calendar cal;
+            CalendarWrapper(Calendar pCalendar) {
+                cal = pCalendar;
+            }
+        }
+
+        /** Returns the calendar value in milliseconds.
 		 * @param pCal Calendar object
 		 * @return <code>pCal.getTime().getTime()</code>.
 		 */
-		public long serializableParam(Calendar pCal) {
-			return pCal.getTime().getTime();
+		public long serializableParam(CalendarWrapper pCal) {
+			return pCal.cal.getTime().getTime();
 		}
-	}
+
+		/** Returns midnight of the following day.
+		 */
+        public Calendar calendarParam(Calendar pCal) {
+            Calendar cal = (Calendar) pCal.clone();
+            cal.add(Calendar.DAY_OF_MONTH, 1);
+            cal.set(Calendar.HOUR_OF_DAY, 0);
+            cal.set(Calendar.MINUTE, 0);
+            cal.set(Calendar.SECOND, 0);
+            cal.set(Calendar.MILLISECOND, 0);
+            return cal;
+        }
+
+        /** Returns midnight of the following day.
+         */
+        public Calendar dateParam(Date pDate) {
+            Calendar cal = Calendar.getInstance();
+            cal.setTime(pDate);
+            return calendarParam(cal);
+        }
+    }
 
 	protected XmlRpcHandlerMapping getHandlerMapping() throws IOException, XmlRpcException {
 		return new PropertyHandlerMapping(getClass().getClassLoader(),
@@ -798,7 +830,7 @@
 	}
 
 	/** Test, whether we can invoke a method, passing an instance of
-	 * [EMAIL PROTECTED] java.io.Serializable} as an instance.
+	 * [EMAIL PROTECTED] java.io.Serializable} as a parameter.
 	 * @throws Exception The test failed.
 	 */
 	public void testSerializableParam() throws Exception {
@@ -810,14 +842,9 @@
 	private void testSerializableParam(ClientProvider pProvider) throws Exception {
 		final String methodName = "Remote.serializableParam";
 		Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
-		cal.set(Calendar.YEAR, 2005);
-		cal.set(Calendar.MONTH, 5);
-		cal.set(Calendar.DAY_OF_MONTH, 23);
-		cal.set(Calendar.HOUR_OF_DAY, 8);
-		cal.set(Calendar.MINUTE, 4);
-		cal.set(Calendar.SECOND, 0);
+		cal.set(2005, 5, 23, 8, 4, 0);
 		cal.set(Calendar.MILLISECOND, 5);
-		final Object[] params = new Object[]{cal};
+		final Object[] params = new Object[]{new Remote.CalendarWrapper(cal)};
 		final XmlRpcClient client = pProvider.getClient();
 		Object result = client.execute(getExConfig(pProvider), methodName, params);
 		assertEquals(new Long(cal.getTime().getTime()), result);
@@ -829,4 +856,62 @@
 		}
 		assertTrue(ok);
 	}
+
+	/** Tests, whether we can invoke a method, passing an instance of
+     * [EMAIL PROTECTED] Calendar} as a parameter.
+     * @throws Exception The test failed.
+	 */
+	public void testCalendarParam() throws Exception {
+	    for (int i = 0;  i < providers.length;  i++) {
+	        testCalendarParam(providers[i]);
+        }
+    }
+
+	private void testCalendarParam(ClientProvider pProvider) throws Exception {
+	    final String methodName = "Remote.calendarParam";
+        Calendar cal1 = newCalendarParam();
+        Calendar cal2 = newCalendarResult();
+        final Object[] params = new Object[]{cal1};
+        final XmlRpcClient client = pProvider.getClient();
+        Object result = client.execute(getExConfig(pProvider), methodName, params);
+        assertEquals(cal2, result);
+        result = client.execute(getConfig(pProvider), methodName, params);
+        assertEquals(cal2, result);
+    }
+
+    private Calendar newCalendarResult() {
+        Calendar cal2 = Calendar.getInstance(TimeZone.getDefault());
+        cal2.set(2005, 5, 24, 0, 0, 0);
+        cal2.set(Calendar.MILLISECOND, 0);
+        return cal2;
+    }
+
+    private Calendar newCalendarParam() {
+        Calendar cal1 = Calendar.getInstance(TimeZone.getDefault());
+        cal1.set(2005, 5, 23, 8, 4, 0);
+        cal1.set(Calendar.MILLISECOND, 5);
+        return cal1;
+    }
+
+    /** Tests, whether we can invoke a method, passing an instance of
+     * [EMAIL PROTECTED] Date} as a parameter.
+     * @throws Exception The test failed.
+     */
+    public void testDateParam() throws Exception {
+        for (int i = 0;  i < providers.length;  i++) {
+            testDateParam(providers[i]);
+        }
+    }
+
+    private void testDateParam(ClientProvider pProvider) throws Exception {
+        final String methodName = "Remote.dateParam";
+        Date date1 = newCalendarParam().getTime();
+        Calendar cal2 = newCalendarResult();
+        final Object[] params = new Object[]{date1};
+        final XmlRpcClient client = pProvider.getClient();
+        Object result = client.execute(getExConfig(pProvider), methodName, params);
+        assertEquals(cal2, result);
+        result = client.execute(getConfig(pProvider), methodName, params);
+        assertEquals(cal2, result);
+    }
 }

Reply via email to