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