Author: jochen Date: Fri Jun 23 19:59:44 2006 New Revision: 416856 URL: http://svn.apache.org/viewvc?rev=416856&view=rev Log: Added partial support for automatic conversion of object arrays to lists, or vectors. Same for maps to hash tables, or properties.
Added: webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/TypeConverter.java webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/TypeConverterFactory.java webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/TypeConverterFactoryImpl.java webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/JiraTest.java webservices/xmlrpc/trunk/tests/src/test/resources/org/apache/xmlrpc/test/JiraTest.properties Modified: webservices/xmlrpc/trunk/client/src/main/java/org/apache/xmlrpc/client/XmlRpcLocalTransport.java webservices/xmlrpc/trunk/client/src/main/java/org/apache/xmlrpc/client/util/ClientFactory.java webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/LocalStreamConnection.java webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/ServerStreamConnection.java webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/XmlRpcRequestProcessor.java webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/metadata/ReflectiveXmlRpcMetaDataHandler.java webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/metadata/Util.java webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/AbstractReflectiveHandlerMapping.java webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/DynamicHandlerMapping.java webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/PropertyHandlerMapping.java webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/ReflectiveXmlRpcHandler.java webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/XmlRpcLocalStreamServer.java webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/XmlRpcServer.java webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/XmlRpcServlet.java webservices/xmlrpc/trunk/src/changes/changes.xml webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/BaseTest.java webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/DynamicProxyTest.java webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/XmlRpcTestCase.java Modified: webservices/xmlrpc/trunk/client/src/main/java/org/apache/xmlrpc/client/XmlRpcLocalTransport.java URL: http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/client/src/main/java/org/apache/xmlrpc/client/XmlRpcLocalTransport.java?rev=416856&r1=416855&r2=416856&view=diff ============================================================================== --- webservices/xmlrpc/trunk/client/src/main/java/org/apache/xmlrpc/client/XmlRpcLocalTransport.java (original) +++ webservices/xmlrpc/trunk/client/src/main/java/org/apache/xmlrpc/client/XmlRpcLocalTransport.java Fri Jun 23 19:59:44 2006 @@ -15,6 +15,7 @@ */ package org.apache.xmlrpc.client; +import java.util.Collection; import java.util.Date; import java.util.Iterator; import java.util.Map; @@ -22,7 +23,10 @@ import org.apache.xmlrpc.XmlRpcConfig; import org.apache.xmlrpc.XmlRpcException; import org.apache.xmlrpc.XmlRpcRequest; +import org.apache.xmlrpc.common.TypeConverter; +import org.apache.xmlrpc.common.TypeConverterFactory; import org.apache.xmlrpc.common.XmlRpcExtensionException; +import org.apache.xmlrpc.common.XmlRpcRequestProcessor; /** The default implementation of a local transport. */ @@ -45,6 +49,13 @@ } } return false; + } else if (pObject instanceof Collection) { + for (Iterator iter = ((Collection) pObject).iterator(); iter.hasNext(); ) { + if (isExtensionType(iter.next())) { + return true; + } + } + return false; } else if (pObject instanceof Map) { Map map = (Map) pObject; for (Iterator iter = map.entrySet().iterator(); iter.hasNext(); ) { @@ -72,9 +83,10 @@ } } } - Object result; + final XmlRpcRequestProcessor server = ((XmlRpcLocalClientConfig) config).getXmlRpcServer(); + Object result; try { - result = ((XmlRpcLocalClientConfig) config).getXmlRpcServer().execute(pRequest); + result = server.execute(pRequest); } catch (Throwable t) { if (t instanceof XmlRpcClientException) { throw (XmlRpcClientException) t; @@ -88,6 +100,12 @@ throw new XmlRpcExtensionException("Result has invalid type, if isEnabledForExtensions() == false"); } } - return result; + + if (result == null) { + return null; + } + final TypeConverterFactory typeConverterFactory = server.getTypeConverterFactory(); + final TypeConverter typeConverter = typeConverterFactory.getTypeConverter(result.getClass()); + return typeConverter.backConvert(result); } } Modified: webservices/xmlrpc/trunk/client/src/main/java/org/apache/xmlrpc/client/util/ClientFactory.java URL: http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/client/src/main/java/org/apache/xmlrpc/client/util/ClientFactory.java?rev=416856&r1=416855&r2=416856&view=diff ============================================================================== --- webservices/xmlrpc/trunk/client/src/main/java/org/apache/xmlrpc/client/util/ClientFactory.java (original) +++ webservices/xmlrpc/trunk/client/src/main/java/org/apache/xmlrpc/client/util/ClientFactory.java Fri Jun 23 19:59:44 2006 @@ -20,6 +20,9 @@ import java.lang.reflect.Proxy; import org.apache.xmlrpc.client.XmlRpcClient; +import org.apache.xmlrpc.common.TypeConverter; +import org.apache.xmlrpc.common.TypeConverterFactory; +import org.apache.xmlrpc.common.TypeConverterFactoryImpl; /** @@ -31,16 +34,32 @@ */ public class ClientFactory { private final XmlRpcClient client; + private final TypeConverterFactory typeConverterFactory; private boolean objectMethodLocal; /** Creates a new instance. * @param pClient A fully configured XML-RPC client, which is * used internally to perform XML-RPC calls. + * @param pTypeConverterFactory Creates instances of [EMAIL PROTECTED] TypeConverterFactory}, + * which are used to transform the result object in its target representation. */ - public ClientFactory(XmlRpcClient pClient) { + public ClientFactory(XmlRpcClient pClient, TypeConverterFactory pTypeConverterFactory) { + typeConverterFactory = pTypeConverterFactory; client = pClient; } + /** Creates a new instance. Shortcut for + * <pre> + * new ClientFactory(pClient, new TypeConverterFactoryImpl()); + * </pre> + * @param pClient A fully configured XML-RPC client, which is + * used internally to perform XML-RPC calls. + * @see TypeConverterFactoryImpl + */ + public ClientFactory(XmlRpcClient pClient) { + this(pClient, new TypeConverterFactoryImpl()); + } + /** Returns the factories client. */ public XmlRpcClient getClient() { @@ -82,7 +101,9 @@ return pMethod.invoke(pProxy, pArgs); } String methodName = pClass.getName() + "." + pMethod.getName(); - return client.execute(methodName, pArgs); + Object result = client.execute(methodName, pArgs); + TypeConverter typeConverter = typeConverterFactory.getTypeConverter(pMethod.getReturnType()); + return typeConverter.convert(result); } }); } Modified: webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/LocalStreamConnection.java URL: http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/LocalStreamConnection.java?rev=416856&r1=416855&r2=416856&view=diff ============================================================================== --- webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/LocalStreamConnection.java (original) +++ webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/LocalStreamConnection.java Fri Jun 23 19:59:44 2006 @@ -1,3 +1,18 @@ +/* + * Copyright 1999,2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.apache.xmlrpc.common; import java.io.ByteArrayOutputStream; Modified: webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/ServerStreamConnection.java URL: http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/ServerStreamConnection.java?rev=416856&r1=416855&r2=416856&view=diff ============================================================================== --- webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/ServerStreamConnection.java (original) +++ webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/ServerStreamConnection.java Fri Jun 23 19:59:44 2006 @@ -1,3 +1,18 @@ +/* + * Copyright 1999,2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.apache.xmlrpc.common; import java.io.IOException; Added: webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/TypeConverter.java URL: http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/TypeConverter.java?rev=416856&view=auto ============================================================================== --- webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/TypeConverter.java (added) +++ webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/TypeConverter.java Fri Jun 23 19:59:44 2006 @@ -0,0 +1,44 @@ +/* + * Copyright 1999,2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.xmlrpc.common; + +import java.util.List; +import java.util.Vector; + + +/** A [EMAIL PROTECTED] TypeConverter} is used when actually calling the + * handler method or actually returning the result object. It's + * purpose is to convert a single parameter or the return value + * from a generic representation (for example an array of objects) + * to an alternative representation, which is actually used in + * the methods signature (for example [EMAIL PROTECTED] List}, or + * [EMAIL PROTECTED] Vector}. + */ +public interface TypeConverter { + /** Returns, whether the [EMAIL PROTECTED] TypeConverter} is + * ready to handle the given object. If so, + * [EMAIL PROTECTED] #convert(Object)} may be called. + */ + boolean isConvertable(Object pObject); + /** Converts the given object into the required + * representation. + */ + Object convert(Object pObject); + /** Converts the given object into its generic + * representation. + */ + Object backConvert(Object result); +} Added: webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/TypeConverterFactory.java URL: http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/TypeConverterFactory.java?rev=416856&view=auto ============================================================================== --- webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/TypeConverterFactory.java (added) +++ webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/TypeConverterFactory.java Fri Jun 23 19:59:44 2006 @@ -0,0 +1,27 @@ +/* + * Copyright 1999,2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.xmlrpc.common; + + +/** A [EMAIL PROTECTED] TypeConverterFactory} is called for creating instances + * of [EMAIL PROTECTED] TypeConverter}. + */ +public interface TypeConverterFactory { + /** Creates an instance of [EMAIL PROTECTED] TypeFactory}, which may be + * used to create instances of the given class. + */ + TypeConverter getTypeConverter(Class pClass); +} Added: webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/TypeConverterFactoryImpl.java URL: http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/TypeConverterFactoryImpl.java?rev=416856&view=auto ============================================================================== --- webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/TypeConverterFactoryImpl.java (added) +++ webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/TypeConverterFactoryImpl.java Fri Jun 23 19:59:44 2006 @@ -0,0 +1,291 @@ +/* + * Copyright 1999,2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.xmlrpc.common; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collection; +import java.util.Date; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Vector; + +import org.w3c.dom.Document; + + +/** Default implementation of [EMAIL PROTECTED] TypeConverterFactory}. + */ +public class TypeConverterFactoryImpl implements TypeConverterFactory { + private static class IdentityTypeConverter implements TypeConverter { + private final Class clazz; + IdentityTypeConverter(Class pClass) { + clazz = pClass; + } + public boolean isConvertable(Object pObject) { + return pObject == null || clazz.isAssignableFrom(pObject.getClass()); + } + public Object convert(Object pObject) { + return pObject; + } + public Object backConvert(Object pObject) { + return pObject; + } + } + + private static abstract class ListTypeConverter implements TypeConverter { + private final Class clazz; + ListTypeConverter(Class pClass) { + clazz = pClass; + } + protected abstract List newList(int pSize); + + public boolean isConvertable(Object pObject) { + return pObject == null || pObject instanceof Object[] || pObject instanceof Collection; + } + + public Object convert(Object pObject) { + if (pObject == null) { + return null; + } + if (clazz.isAssignableFrom(pObject.getClass())) { + return pObject; + } + if (pObject instanceof Object[]) { + Object[] objects = (Object[]) pObject; + List result = newList(objects.length); + for (int i = 0; i < objects.length; i++) { + result.add(objects[i]); + } + return result; + } + Collection collection = (Collection) pObject; + List result = newList(collection.size()); + result.addAll(collection); + return result; + } + + public Object backConvert(Object pObject) { + return ((List) pObject).toArray(); + } + } + + private static class PrimitiveTypeConverter implements TypeConverter { + private final Class clazz; + PrimitiveTypeConverter(Class pClass) { + clazz = pClass; + } + public boolean isConvertable(Object pObject) { + return pObject != null && pObject.getClass().isAssignableFrom(clazz); + } + public Object convert(Object pObject) { + return pObject; + } + public Object backConvert(Object pObject) { + return pObject; + } + } + + private static final TypeConverter mapTypeConverter = new IdentityTypeConverter(Map.class); + private static final TypeConverter objectArrayTypeConverter = new IdentityTypeConverter(Object[].class); + private static final TypeConverter byteArrayTypeConverter = new IdentityTypeConverter(byte[].class); + private static final TypeConverter stringTypeConverter = new IdentityTypeConverter(String.class); + private static final TypeConverter booleanTypeConverter = new IdentityTypeConverter(Boolean.class); + private static final TypeConverter characterTypeConverter = new IdentityTypeConverter(Character.class); + private static final TypeConverter byteTypeConverter = new IdentityTypeConverter(Byte.class); + private static final TypeConverter shortTypeConverter = new IdentityTypeConverter(Short.class); + private static final TypeConverter integerTypeConverter = new IdentityTypeConverter(Integer.class); + private static final TypeConverter longTypeConverter = new IdentityTypeConverter(Long.class); + private static final TypeConverter bigDecimalTypeConverter = new IdentityTypeConverter(BigDecimal.class); + private static final TypeConverter bigIntegerTypeConverter = new IdentityTypeConverter(BigInteger.class); + private static final TypeConverter floatTypeConverter = new IdentityTypeConverter(Float.class); + private static final TypeConverter doubleTypeConverter = new IdentityTypeConverter(Double.class); + private static final TypeConverter dateTypeConverter = new IdentityTypeConverter(Date.class); + private static final TypeConverter calendarTypeConverter = new IdentityTypeConverter(Calendar.class); + private static final TypeConverter domTypeConverter = new IdentityTypeConverter(Document.class); + private static final TypeConverter primitiveBooleanTypeConverter = new PrimitiveTypeConverter(Boolean.class); + private static final TypeConverter primitiveCharTypeConverter = new PrimitiveTypeConverter(Character.class); + private static final TypeConverter primitiveByteTypeConverter = new PrimitiveTypeConverter(Byte.class); + private static final TypeConverter primitiveShortTypeConverter = new PrimitiveTypeConverter(Short.class); + private static final TypeConverter primitiveIntTypeConverter = new PrimitiveTypeConverter(Integer.class); + private static final TypeConverter primitiveLongTypeConverter = new PrimitiveTypeConverter(Long.class); + private static final TypeConverter primitiveFloatTypeConverter = new PrimitiveTypeConverter(Float.class); + private static final TypeConverter primitiveDoubleTypeConverter = new PrimitiveTypeConverter(Double.class); + + private static final TypeConverter propertiesTypeConverter = new TypeConverter() { + public boolean isConvertable(Object pObject) { + return pObject == null || pObject instanceof Map; + } + + public Object convert(Object pObject) { + if (pObject == null) { + return null; + } + Properties props = new Properties(); + props.putAll((Map) pObject); + return props; + } + + public Object backConvert(Object pObject) { + return pObject; + } + }; + + private static final TypeConverter hashTableTypeConverter = new TypeConverter() { + public boolean isConvertable(Object pObject) { + return pObject == null || pObject instanceof Map; + } + + public Object convert(Object pObject) { + if (pObject == null) { + return null; + } + return new Hashtable((Map) pObject); + } + + public Object backConvert(Object pObject) { + return pObject; + } + }; + + private static final TypeConverter listTypeConverter = new ListTypeConverter(List.class) { + protected List newList(int pSize) { + return new ArrayList(pSize); + } + }; + + private static final TypeConverter vectorTypeConverter = new ListTypeConverter(Vector.class) { + protected List newList(int pSize) { + return new Vector(pSize); + } + }; + + private static class CastCheckingTypeConverter implements TypeConverter { + private final Class clazz; + CastCheckingTypeConverter(Class pClass) { + clazz = pClass; + } + public boolean isConvertable(Object pObject) { + return pObject == null || clazz.isAssignableFrom(pObject.getClass()); + } + public Object convert(Object pObject) { + return pObject; + } + public Object backConvert(Object pObject) { + return pObject; + } + } + + /** Returns a type converter for the given class. + */ + public TypeConverter getTypeConverter(Class pClass) { + if (pClass.isAssignableFrom(boolean.class)) { + return primitiveBooleanTypeConverter; + } + if (pClass.isAssignableFrom(char.class)) { + return primitiveCharTypeConverter; + } + if (pClass.isAssignableFrom(byte.class)) { + return primitiveByteTypeConverter; + } + if (pClass.isAssignableFrom(short.class)) { + return primitiveShortTypeConverter; + } + if (pClass.isAssignableFrom(int.class)) { + return primitiveIntTypeConverter; + } + if (pClass.isAssignableFrom(long.class)) { + return primitiveLongTypeConverter; + } + if (pClass.isAssignableFrom(float.class)) { + return primitiveFloatTypeConverter; + } + if (pClass.isAssignableFrom(double.class)) { + return primitiveDoubleTypeConverter; + } + if (pClass.isAssignableFrom(String.class)) { + return stringTypeConverter; + } + if (pClass.isAssignableFrom(Boolean.class)) { + return booleanTypeConverter; + } + if (pClass.isAssignableFrom(Character.class)) { + return characterTypeConverter; + } + if (pClass.isAssignableFrom(Byte.class)) { + return byteTypeConverter; + } + if (pClass.isAssignableFrom(Short.class)) { + return shortTypeConverter; + } + if (pClass.isAssignableFrom(Integer.class)) { + return integerTypeConverter; + } + if (pClass.isAssignableFrom(Long.class)) { + return longTypeConverter; + } + if (pClass.isAssignableFrom(BigDecimal.class)) { + return bigDecimalTypeConverter; + } + if (pClass.isAssignableFrom(BigInteger.class)) { + return bigIntegerTypeConverter; + } + if (pClass.isAssignableFrom(Float.class)) { + return floatTypeConverter; + } + if (pClass.isAssignableFrom(Double.class)) { + return doubleTypeConverter; + } + if (pClass.isAssignableFrom(Date.class)) { + return dateTypeConverter; + } + if (pClass.isAssignableFrom(Calendar.class)) { + return calendarTypeConverter; + } + if (pClass.isAssignableFrom(Object[].class)) { + return objectArrayTypeConverter; + } + if (pClass.isAssignableFrom(List.class)) { + return listTypeConverter; + } + if (pClass.isAssignableFrom(Vector.class)) { + return vectorTypeConverter; + } + if (pClass.isAssignableFrom(Map.class)) { + return mapTypeConverter; + } + if (pClass.isAssignableFrom(Hashtable.class)) { + return hashTableTypeConverter; + } + if (pClass.isAssignableFrom(Properties.class)) { + return propertiesTypeConverter; + } + if (pClass.isAssignableFrom(byte[].class)) { + return byteArrayTypeConverter; + } + if (pClass.isAssignableFrom(Document.class)) { + return domTypeConverter; + } + if (Serializable.class.isAssignableFrom(pClass)) { + return new CastCheckingTypeConverter(pClass); + } + throw new IllegalStateException("Invalid parameter or result type: " + pClass.getName()); + } +} Modified: webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/XmlRpcRequestProcessor.java URL: http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/XmlRpcRequestProcessor.java?rev=416856&r1=416855&r2=416856&view=diff ============================================================================== --- webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/XmlRpcRequestProcessor.java (original) +++ webservices/xmlrpc/trunk/common/src/main/java/org/apache/xmlrpc/common/XmlRpcRequestProcessor.java Fri Jun 23 19:59:44 2006 @@ -13,4 +13,8 @@ * @throws XmlRpcException Processing the request failed. */ Object execute(XmlRpcRequest pRequest) throws XmlRpcException; + + /** Returns the request processors [EMAIL PROTECTED] TypeConverterFactory}. + */ + TypeConverterFactory getTypeConverterFactory(); } Modified: webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/metadata/ReflectiveXmlRpcMetaDataHandler.java URL: http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/metadata/ReflectiveXmlRpcMetaDataHandler.java?rev=416856&r1=416855&r2=416856&view=diff ============================================================================== --- webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/metadata/ReflectiveXmlRpcMetaDataHandler.java (original) +++ webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/metadata/ReflectiveXmlRpcMetaDataHandler.java Fri Jun 23 19:59:44 2006 @@ -18,6 +18,7 @@ import java.lang.reflect.Method; import org.apache.xmlrpc.XmlRpcException; +import org.apache.xmlrpc.common.TypeConverterFactory; import org.apache.xmlrpc.server.AbstractReflectiveHandlerMapping; import org.apache.xmlrpc.server.ReflectiveXmlRpcHandler; @@ -58,10 +59,11 @@ * by [EMAIL PROTECTED] #getMethodHelp()}. */ public ReflectiveXmlRpcMetaDataHandler(AbstractReflectiveHandlerMapping pMapping, + TypeConverterFactory pTypeConverterFactory, Class pClass, boolean pInstanceIsStateless, Method[] pMethods, String[][] pSignatures, String pMethodHelp) throws XmlRpcException { - super(pMapping, pClass, pInstanceIsStateless, pMethods); + super(pMapping, pTypeConverterFactory, pClass, pInstanceIsStateless, pMethods); signatures = pSignatures; methodHelp = pMethodHelp; } Modified: webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/metadata/Util.java URL: http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/metadata/Util.java?rev=416856&r1=416855&r2=416856&view=diff ============================================================================== --- webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/metadata/Util.java (original) +++ webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/metadata/Util.java Fri Jun 23 19:59:44 2006 @@ -185,62 +185,6 @@ return sb.toString(); } - /** Returns, whether the given methods signature is matched by - * the given parameter set. - */ - public static boolean isMatching(Method method, Object[] args) { - Class[] parameterClasses = method.getParameterTypes(); - if (parameterClasses.length != args.length) { - return false; - } - for (int i = 0; i < args.length; i++) { - if (!isMatching(parameterClasses[i], args[i])) { - return false; - } - } - return true; - } - - /** Returns, whether the given parameter matches the given - * type. - */ - public static boolean isMatching(Class pParameterType, Object pArg) { - if (pArg == null) { - return !pParameterType.isPrimitive(); - } - final Class c; - if (pParameterType.isPrimitive()) { - c = getObjectClass(pParameterType); - } else { - c = pParameterType; - } - return c.isAssignableFrom(pArg.getClass()); - } - - /** Given a primitive class, returns the corresponding object class. - */ - public static Class getObjectClass(Class pPrimitiveClass) { - if (byte.class.equals(pPrimitiveClass)) { - return Byte.class; - } else if (short.class.equals(pPrimitiveClass)) { - return Short.class; - } else if (int.class.equals(pPrimitiveClass)) { - return Integer.class; - } else if (long.class.equals(pPrimitiveClass)) { - return Long.class; - } else if (float.class.equals(pPrimitiveClass)) { - return Float.class; - } else if (double.class.equals(pPrimitiveClass)) { - return Double.class; - } else if (char.class.equals(pPrimitiveClass)) { - return Character.class; - } else if (boolean.class.equals(pPrimitiveClass)) { - return Boolean.class; - } else { - throw new IllegalStateException("Invalid primitive class: " + pPrimitiveClass.getName()); - } - } - /** Returns a signature for the given parameter set. This is used * in error messages. */ Modified: webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/AbstractReflectiveHandlerMapping.java URL: http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/AbstractReflectiveHandlerMapping.java?rev=416856&r1=416855&r2=416856&view=diff ============================================================================== --- webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/AbstractReflectiveHandlerMapping.java (original) +++ webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/AbstractReflectiveHandlerMapping.java Fri Jun 23 19:59:44 2006 @@ -26,6 +26,7 @@ import org.apache.xmlrpc.XmlRpcException; import org.apache.xmlrpc.XmlRpcHandler; import org.apache.xmlrpc.XmlRpcRequest; +import org.apache.xmlrpc.common.TypeConverterFactory; import org.apache.xmlrpc.metadata.ReflectiveXmlRpcMetaDataHandler; import org.apache.xmlrpc.metadata.Util; import org.apache.xmlrpc.metadata.XmlRpcListableHandlerMapping; @@ -59,10 +60,11 @@ throws XmlRpcException; } + private final TypeConverterFactory typeConverterFactory; + private final boolean instanceIsStateless; protected Map handlerMap = new HashMap(); private AuthenticationHandler authenticationHandler; private InitializationHandler initializationHandler; - private final boolean instanceIsStateless; /** Creates a new instance. * @param pInstanceIsStateless The handler @@ -81,7 +83,9 @@ * and the like.</li> * </ol> */ - protected AbstractReflectiveHandlerMapping(boolean pInstanceIsStateless) { + protected AbstractReflectiveHandlerMapping(TypeConverterFactory pTypeConverterFactory, + boolean pInstanceIsStateless) { + typeConverterFactory = pTypeConverterFactory; instanceIsStateless = pInstanceIsStateless; } @@ -178,10 +182,11 @@ String[][] sig = getSignature(pMethods); String help = getMethodHelp(pClass, pMethods); if (sig == null || help == null) { - return new ReflectiveXmlRpcHandler(this, pClass, instanceIsStateless, pMethods); + return new ReflectiveXmlRpcHandler(this, typeConverterFactory, + pClass, instanceIsStateless, pMethods); } - return new ReflectiveXmlRpcMetaDataHandler(this, pClass, instanceIsStateless, - pMethods, sig, help); + return new ReflectiveXmlRpcMetaDataHandler(this, typeConverterFactory, + pClass, instanceIsStateless, pMethods, sig, help); } /** Creates a signature for the given method. Modified: webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/DynamicHandlerMapping.java URL: http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/DynamicHandlerMapping.java?rev=416856&r1=416855&r2=416856&view=diff ============================================================================== --- webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/DynamicHandlerMapping.java (original) +++ webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/DynamicHandlerMapping.java Fri Jun 23 19:59:44 2006 @@ -3,6 +3,7 @@ import java.util.Iterator; import org.apache.xmlrpc.XmlRpcException; +import org.apache.xmlrpc.common.TypeConverterFactory; /** A handler mapping, which requires explicit registration @@ -26,8 +27,9 @@ * and the like.</li> * </ol> */ - public DynamicHandlerMapping(boolean pInstanceIsStateless) { - super(pInstanceIsStateless); + public DynamicHandlerMapping(TypeConverterFactory pTypeConverterFactory, + boolean pInstanceIsStateless) { + super(pTypeConverterFactory, pInstanceIsStateless); } /** Adds handlers for the given object to the mapping. Modified: webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/PropertyHandlerMapping.java URL: http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/PropertyHandlerMapping.java?rev=416856&r1=416855&r2=416856&view=diff ============================================================================== --- webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/PropertyHandlerMapping.java (original) +++ webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/PropertyHandlerMapping.java Fri Jun 23 19:59:44 2006 @@ -23,6 +23,7 @@ import java.util.Properties; import org.apache.xmlrpc.XmlRpcException; +import org.apache.xmlrpc.common.TypeConverterFactory; /** A handler mapping based on a property file. The property file @@ -64,9 +65,10 @@ * @throws XmlRpcException Initializing the handlers failed. */ public PropertyHandlerMapping(ClassLoader pClassLoader, URL pURL, + TypeConverterFactory pTypeConverterFactory, boolean pInstanceIsStateless) throws IOException, XmlRpcException { - super(pInstanceIsStateless); + super(pTypeConverterFactory, pInstanceIsStateless); handlerMap = load(pClassLoader, pURL); } @@ -94,9 +96,11 @@ * @throws XmlRpcException Initializing the handlers failed. */ public PropertyHandlerMapping(ClassLoader pClassLoader, String pResource, + TypeConverterFactory pTypeConverterFactory, boolean pInstanceIsStateless) throws IOException, XmlRpcException { - this(pClassLoader, asURL(pClassLoader, pResource), pInstanceIsStateless); + this(pClassLoader, asURL(pClassLoader, pResource), pTypeConverterFactory, + pInstanceIsStateless); } private static URL asURL(ClassLoader pClassLoader, String pResource) throws IOException { Modified: webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/ReflectiveXmlRpcHandler.java URL: http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/ReflectiveXmlRpcHandler.java?rev=416856&r1=416855&r2=416856&view=diff ============================================================================== --- webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/ReflectiveXmlRpcHandler.java (original) +++ webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/ReflectiveXmlRpcHandler.java Fri Jun 23 19:59:44 2006 @@ -21,6 +21,8 @@ import org.apache.xmlrpc.XmlRpcException; import org.apache.xmlrpc.XmlRpcHandler; import org.apache.xmlrpc.XmlRpcRequest; +import org.apache.xmlrpc.common.TypeConverter; +import org.apache.xmlrpc.common.TypeConverterFactory; import org.apache.xmlrpc.common.XmlRpcNotAuthorizedException; import org.apache.xmlrpc.metadata.Util; import org.apache.xmlrpc.server.AbstractReflectiveHandlerMapping.AuthenticationHandler; @@ -30,9 +32,21 @@ /** Default implementation of [EMAIL PROTECTED] XmlRpcHandler}. */ public class ReflectiveXmlRpcHandler implements XmlRpcHandler { - private final AbstractReflectiveHandlerMapping mapping; + private static class MethodData { + final Method method; + final TypeConverter[] typeConverters; + MethodData(Method pMethod, TypeConverterFactory pTypeConverterFactory) { + method = pMethod; + Class[] paramClasses = method.getParameterTypes(); + typeConverters = new TypeConverter[paramClasses.length]; + for (int i = 0; i < paramClasses.length; i++) { + typeConverters[i] = pTypeConverterFactory.getTypeConverter(paramClasses[i]); + } + } + } + private final AbstractReflectiveHandlerMapping mapping; private final Class clazz; - private final Method[] methods; + private final MethodData[] methods; private final Object theInstance; /** Creates a new instance. @@ -60,11 +74,15 @@ * executing the handler. */ public ReflectiveXmlRpcHandler(AbstractReflectiveHandlerMapping pMapping, + TypeConverterFactory pTypeConverterFactory, Class pClass, boolean pInstanceIsStateless, Method[] pMethods) throws XmlRpcException { mapping = pMapping; clazz = pClass; - methods = pMethods; + methods = new MethodData[pMethods.length]; + for (int i = 0; i < methods.length; i++) { + methods[i] = new MethodData(pMethods[i], pTypeConverterFactory); + } theInstance = pInstanceIsStateless ? newInstance() : null; } @@ -89,16 +107,26 @@ args[j] = pRequest.getParameter(j); } Object instance = getInstance(pRequest); - if (methods.length == 1) { - return invoke(instance, methods[0], args); - } else { - for (int i = 0; i < methods.length; i++) { - if (Util.isMatching(methods[i], args)) { - return invoke(instance, methods[i], args); + for (int i = 0; i < methods.length; i++) { + MethodData methodData = methods[i]; + TypeConverter[] converters = methodData.typeConverters; + if (args.length == converters.length) { + boolean matching = true; + for (int j = 0; j < args.length; j++) { + if (!converters[j].isConvertable(args[i])) { + matching = false; + break; + } + } + if (matching) { + for (int j = 0; j < args.length; j++) { + args[i] = converters[i].convert(args[i]); + } + return invoke(instance, methodData.method, args); } } - throw new XmlRpcException("No method matching arguments: " + Util.getSignature(args)); - } + } + throw new XmlRpcException("No method matching arguments: " + Util.getSignature(args)); } private Object invoke(Object pInstance, Method pMethod, Object[] pArgs) throws XmlRpcException { Modified: webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/XmlRpcLocalStreamServer.java URL: http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/XmlRpcLocalStreamServer.java?rev=416856&r1=416855&r2=416856&view=diff ============================================================================== --- webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/XmlRpcLocalStreamServer.java (original) +++ webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/XmlRpcLocalStreamServer.java Fri Jun 23 19:59:44 2006 @@ -1,15 +1,9 @@ package org.apache.xmlrpc.server; -import java.io.IOException; -import java.io.OutputStream; - import org.apache.xmlrpc.XmlRpcException; import org.apache.xmlrpc.XmlRpcRequest; -import org.apache.xmlrpc.common.LocalStreamConnection; -import org.apache.xmlrpc.common.ServerStreamConnection; import org.apache.xmlrpc.common.XmlRpcRequestProcessor; import org.apache.xmlrpc.common.XmlRpcRequestProcessorFactory; -import org.apache.xmlrpc.common.XmlRpcStreamRequestConfig; /** Server part of a local stream transport. Modified: webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/XmlRpcServer.java URL: http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/XmlRpcServer.java?rev=416856&r1=416855&r2=416856&view=diff ============================================================================== --- webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/XmlRpcServer.java (original) +++ webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/XmlRpcServer.java Fri Jun 23 19:59:44 2006 @@ -18,6 +18,8 @@ import org.apache.xmlrpc.XmlRpcConfig; import org.apache.xmlrpc.XmlRpcException; import org.apache.xmlrpc.XmlRpcRequest; +import org.apache.xmlrpc.common.TypeConverterFactory; +import org.apache.xmlrpc.common.TypeConverterFactoryImpl; import org.apache.xmlrpc.common.XmlRpcController; import org.apache.xmlrpc.common.XmlRpcRequestProcessor; import org.apache.xmlrpc.common.XmlRpcWorkerFactory; @@ -32,11 +34,21 @@ public class XmlRpcServer extends XmlRpcController implements XmlRpcRequestProcessor { private XmlRpcHandlerMapping handlerMapping; + private TypeConverterFactory typeConverterFactory = new TypeConverterFactoryImpl(); private XmlRpcServerConfig config = new XmlRpcServerConfigImpl(); protected XmlRpcWorkerFactory getDefaultXmlRpcWorkerFactory() { return new XmlRpcServerWorkerFactory(this); } + + /** Sets the servers [EMAIL PROTECTED] TypeConverterFactory}. + */ + public void setTypeConverterFactory(TypeConverterFactory pFactory) { + typeConverterFactory = pFactory; + } + public TypeConverterFactory getTypeConverterFactory() { + return typeConverterFactory; + } /** Sets the servers configuration. * @param pConfig The new server configuration. Modified: webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/XmlRpcServlet.java URL: http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/XmlRpcServlet.java?rev=416856&r1=416855&r2=416856&view=diff ============================================================================== --- webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/XmlRpcServlet.java (original) +++ webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/webserver/XmlRpcServlet.java Fri Jun 23 19:59:44 2006 @@ -29,6 +29,7 @@ import org.apache.xmlrpc.server.PropertyHandlerMapping; import org.apache.xmlrpc.server.XmlRpcHandlerMapping; import org.apache.xmlrpc.server.XmlRpcServer; +import org.apache.xmlrpc.server.XmlRpcServerConfig; import org.apache.xmlrpc.server.XmlRpcServerConfigImpl; @@ -104,7 +105,9 @@ * [EMAIL PROTECTED] #newXmlRpcHandlerMapping()}. */ protected PropertyHandlerMapping newPropertyHandlerMapping(URL url) throws IOException, XmlRpcException { - return new PropertyHandlerMapping(getClass().getClassLoader(), url, false); + return new PropertyHandlerMapping(getClass().getClassLoader(), url, + server.getTypeConverterFactory(), + false); } /** Creates a new instance of [EMAIL PROTECTED] org.apache.xmlrpc.webserver.RequestData} Modified: webservices/xmlrpc/trunk/src/changes/changes.xml URL: http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/src/changes/changes.xml?rev=416856&r1=416855&r2=416856&view=diff ============================================================================== --- webservices/xmlrpc/trunk/src/changes/changes.xml (original) +++ webservices/xmlrpc/trunk/src/changes/changes.xml Fri Jun 23 19:59:44 2006 @@ -70,6 +70,10 @@ It is now possible to create and initialize handler objects per request. </action> + <action dev="jochen" type="fix" issue="XMLRPC-89"> + Added partial support for automatic conversion of object arrays + to lists, or vectors. Same for maps to hash tables, or properties. + </action> </release> <release version="3.0a1" date="17-Feb-2005"> <action dev="jochen" type="add"> Modified: webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/BaseTest.java URL: http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/BaseTest.java?rev=416856&r1=416855&r2=416856&view=diff ============================================================================== --- webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/BaseTest.java (original) +++ webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/BaseTest.java Fri Jun 23 19:59:44 2006 @@ -31,8 +31,6 @@ import org.apache.xmlrpc.XmlRpcException; import org.apache.xmlrpc.client.XmlRpcClient; -import org.apache.xmlrpc.client.XmlRpcClientConfig; -import org.apache.xmlrpc.client.XmlRpcClientConfigImpl; import org.apache.xmlrpc.common.XmlRpcExtensionException; import org.apache.xmlrpc.server.PropertyHandlerMapping; import org.apache.xmlrpc.server.XmlRpcHandlerMapping; @@ -281,9 +279,10 @@ } } - protected XmlRpcHandlerMapping getHandlerMapping() throws IOException, XmlRpcException { + protected XmlRpcHandlerMapping getHandlerMapping() throws IOException, XmlRpcException { return new PropertyHandlerMapping(getClass().getClassLoader(), getClass().getResource("BaseTest.properties"), + getTypeConverterFactory(), true); } Modified: webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/DynamicProxyTest.java URL: http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/DynamicProxyTest.java?rev=416856&r1=416855&r2=416856&view=diff ============================================================================== --- webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/DynamicProxyTest.java (original) +++ webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/DynamicProxyTest.java Fri Jun 23 19:59:44 2006 @@ -48,6 +48,7 @@ protected XmlRpcHandlerMapping getHandlerMapping() throws IOException, XmlRpcException { return new PropertyHandlerMapping(getClass().getClassLoader(), getClass().getResource("DynamicProxyTest.properties"), + getTypeConverterFactory(), true); } Added: webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/JiraTest.java URL: http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/JiraTest.java?rev=416856&view=auto ============================================================================== --- webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/JiraTest.java (added) +++ webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/JiraTest.java Fri Jun 23 19:59:44 2006 @@ -0,0 +1,192 @@ +/* + * Copyright 1999,2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.xmlrpc.test; + +import java.io.IOException; +import java.util.Collections; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Map; +import java.util.Properties; +import java.util.Vector; + +import org.apache.xmlrpc.XmlRpcException; +import org.apache.xmlrpc.client.XmlRpcClient; +import org.apache.xmlrpc.client.util.ClientFactory; +import org.apache.xmlrpc.server.PropertyHandlerMapping; +import org.apache.xmlrpc.server.XmlRpcHandlerMapping; + + +/** + * Test case for various jira issues. + */ +public class JiraTest extends XmlRpcTestCase { + /** Interface of the handler for [EMAIL PROTECTED] JiraTest#testXMLRPC89()} + */ + public interface XMLRPC89Handler { + /** + * Returns the reversed vector. + */ + Vector reverse(Vector pVector); + /** + * Returns the same hashtable, but doubles the + * values. + */ + Hashtable doubledValues(Hashtable pMap); + /** + * Returns the same properties, but doubles the + * values. + */ + Properties doubledPropertyValues(Properties pMap); + } + /** + * Handler for [EMAIL PROTECTED] JiraTest#testXMLRPC89()} + */ + public static class XMLRPC89HandlerImpl implements XMLRPC89Handler { + public Vector reverse(Vector pVector) { + Vector result = new Vector(pVector.size()); + result.addAll(pVector); + Collections.reverse(result); + return result; + } + public Hashtable doubledValues(Hashtable pMap) { + final Hashtable result; + if (pMap instanceof Properties) { + result = new Properties(); + } else { + result = new Hashtable(); + } + result.putAll(pMap); + for (Iterator iter = result.entrySet().iterator(); iter.hasNext(); ) { + Map.Entry entry = (Map.Entry) iter.next(); + Object value = entry.getValue(); + final Integer i; + if (pMap instanceof Properties) { + i = Integer.valueOf((String) value); + } else { + i = (Integer) value; + } + Integer iDoubled = new Integer(i.intValue()*2); + if (pMap instanceof Properties) { + entry.setValue(iDoubled.toString()); + } else { + entry.setValue(iDoubled); + } + } + return result; + } + public Properties doubledPropertyValues(Properties pProperties) { + return (Properties) doubledValues(pProperties); + } + } + + protected XmlRpcHandlerMapping getHandlerMapping() throws IOException, + XmlRpcException { + return new PropertyHandlerMapping(getClass().getClassLoader(), + getClass().getResource("JiraTest.properties"), + getTypeConverterFactory(), + true); + } + + /** + * Test case for <a href="http://issues.apache.org/jira/browse/XMLRPC-89"> + * XMLRPC-89</a> + */ + public void testXMLRPC89() throws Exception { + for (int i = 0; i < providers.length; i++) { + testXMLRPC89Vector(providers[i]); + testXMLRPC89Hashtable(providers[i]); + testXMLRPC89Properties(providers[i]); + } + } + + private void testXMLRPC89Vector(ClientProvider pProvider) throws Exception { + Vector values = new Vector(); + for (int i = 0; i < 3; i++) { + values.add(new Integer(i)); + } + Vector params = new Vector(); + params.add(values); + XmlRpcClient client = pProvider.getClient(); + client.setConfig(getConfig(pProvider)); + Object res = client.execute(XMLRPC89Handler.class.getName() + ".reverse", params); + Object[] result = (Object[]) res; + assertNotNull(result); + assertEquals(3, result.length); + for (int i = 0; i < 3; i++) { + assertEquals(new Integer(2-i), result[i]); + } + + ClientFactory factory = new ClientFactory(client); + XMLRPC89Handler handler = (XMLRPC89Handler) factory.newInstance(XMLRPC89Handler.class); + Vector resultVector = handler.reverse(values); + assertNotNull(resultVector); + assertEquals(3, resultVector.size()); + for (int i = 0; i < 3; i++) { + assertEquals(new Integer(2-i), resultVector.get(i)); + } + } + + private void verifyXMLRPC89Hashtable(Map pMap) { + assertNotNull(pMap); + assertEquals(3, pMap.size()); + for (int i = 0; i < 3; i++) { + Integer j = (Integer) pMap.get(String.valueOf(i)); + assertEquals(i*2, j.intValue()); + } + } + + private void testXMLRPC89Hashtable(ClientProvider pProvider) throws Exception { + Hashtable values = new Hashtable(); + for (int i = 0; i < 3; i++) { + values.put(String.valueOf(i), new Integer(i)); + } + XmlRpcClient client = pProvider.getClient(); + client.setConfig(getConfig(pProvider)); + Object res = client.execute(XMLRPC89Handler.class.getName() + ".doubledValues", new Object[]{values}); + verifyXMLRPC89Hashtable((Map) res); + + ClientFactory factory = new ClientFactory(client); + XMLRPC89Handler handler = (XMLRPC89Handler) factory.newInstance(XMLRPC89Handler.class); + Hashtable result = handler.doubledValues(values); + verifyXMLRPC89Hashtable(result); + } + + private void verifyXMLRPC89Properties(Map pMap) { + assertNotNull(pMap); + assertEquals(3, pMap.size()); + for (int i = 0; i < 3; i++) { + String j = (String) pMap.get(String.valueOf(i)); + assertEquals(i*2, Integer.parseInt(j)); + } + } + + private void testXMLRPC89Properties(ClientProvider pProvider) throws Exception { + Properties values = new Properties(); + for (int i = 0; i < 3; i++) { + values.put(String.valueOf(i), String.valueOf(i)); + } + XmlRpcClient client = pProvider.getClient(); + client.setConfig(getConfig(pProvider)); + Object res = client.execute(XMLRPC89Handler.class.getName() + ".doubledPropertyValues", new Object[]{values}); + verifyXMLRPC89Properties((Map) res); + + ClientFactory factory = new ClientFactory(client); + XMLRPC89Handler handler = (XMLRPC89Handler) factory.newInstance(XMLRPC89Handler.class); + Properties result = handler.doubledPropertyValues(values); + verifyXMLRPC89Properties(result); + } +} Modified: webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/XmlRpcTestCase.java URL: http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/XmlRpcTestCase.java?rev=416856&r1=416855&r2=416856&view=diff ============================================================================== --- webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/XmlRpcTestCase.java (original) +++ webservices/xmlrpc/trunk/tests/src/test/java/org/apache/xmlrpc/test/XmlRpcTestCase.java Fri Jun 23 19:59:44 2006 @@ -20,6 +20,8 @@ import org.apache.xmlrpc.XmlRpcException; import org.apache.xmlrpc.client.XmlRpcClientConfig; import org.apache.xmlrpc.client.XmlRpcClientConfigImpl; +import org.apache.xmlrpc.common.TypeConverterFactory; +import org.apache.xmlrpc.common.TypeConverterFactoryImpl; import org.apache.xmlrpc.server.XmlRpcHandlerMapping; import junit.framework.TestCase; @@ -57,5 +59,9 @@ new ServletWebServerProvider(mapping, false) }; } + } + + protected TypeConverterFactory getTypeConverterFactory() { + return new TypeConverterFactoryImpl(); } } Added: webservices/xmlrpc/trunk/tests/src/test/resources/org/apache/xmlrpc/test/JiraTest.properties URL: http://svn.apache.org/viewvc/webservices/xmlrpc/trunk/tests/src/test/resources/org/apache/xmlrpc/test/JiraTest.properties?rev=416856&view=auto ============================================================================== --- webservices/xmlrpc/trunk/tests/src/test/resources/org/apache/xmlrpc/test/JiraTest.properties (added) +++ webservices/xmlrpc/trunk/tests/src/test/resources/org/apache/xmlrpc/test/JiraTest.properties Fri Jun 23 19:59:44 2006 @@ -0,0 +1 @@ +org.apache.xmlrpc.test.JiraTest$XMLRPC89Handler=org.apache.xmlrpc.test.JiraTest$XMLRPC89HandlerImpl --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]