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); + } }