You are viewing a plain text version of this content. The canonical link for it is here.
Posted to xmlrpc-dev@ws.apache.org by jo...@apache.org on 2006/05/22 22:31:58 UTC

svn commit: r408757 - in /webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc: metadata/ReflectiveXmlRpcMetaDataHandler.java metadata/Util.java server/AbstractReflectiveHandlerMapping.java server/ReflectiveXmlRpcHandler.java

Author: jochen
Date: Mon May 22 13:31:57 2006
New Revision: 408757

URL: http://svn.apache.org/viewvc?rev=408757&view=rev
Log:
Added support for method overloading.

Modified:
    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/ReflectiveXmlRpcHandler.java

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=408757&r1=408756&r2=408757&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 Mon May 22 13:31:57 2006
@@ -37,7 +37,7 @@
 	 * messages only.
 	 * @param pInstance The instance, which will be invoked for
 	 * executing the handler.
-	 * @param pMethod The method, which will be invoked for
+	 * @param pMethods The method, which will be invoked for
 	 * executing the handler. 
 	 * @param pSignatures The signature, which will be returned by
 	 * {@link #getSignatures()}.
@@ -45,9 +45,9 @@
 	 * by {@link #getMethodHelp()}.
 	 */
 	public ReflectiveXmlRpcMetaDataHandler(AbstractReflectiveHandlerMapping pMapping,
-			Class pClass, Object pInstance, Method pMethod,
+			Class pClass, Object pInstance, Method[] pMethods,
 			String[][] pSignatures, String pMethodHelp) {
-		super(pMapping, pClass, pInstance, pMethod);
+		super(pMapping, pClass, pInstance, 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=408757&r1=408756&r2=408757&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 Mon May 22 13:31:57 2006
@@ -17,6 +17,7 @@
 
 import java.io.Serializable;
 import java.lang.reflect.Method;
+import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.List;
@@ -94,13 +95,30 @@
 		return null;
 	}
 
-	/** Returns a signature for the given method.
-	 * @param pMethod Method, for which a signature is
+	/** Returns a signature for the given methods.
+	 * @param pMethods Methods, for which a signature is
 	 * being queried.
 	 * @return Signature string, or null, if no signature
 	 * is available.
 	 */
-	public static String[] getSignature(Method pMethod) {
+	public static String[][] getSignature(Method[] pMethods) {
+        final List result = new ArrayList();
+        for (int i = 0;  i < pMethods.length;  i++) {
+            String[] sig = getSignature(pMethods[i]);
+            if (sig != null) {
+                result.add(sig);
+            }
+        }
+        return (String[][]) result.toArray(new String[result.size()][]);
+    }
+
+    /** Returns a signature for the given methods.
+     * @param pMethod Method, for which a signature is
+     * being queried.
+     * @return Signature string, or null, if no signature
+     * is available.
+     */
+    public static String[] getSignature(Method pMethod) {    
 		Class[] paramClasses = pMethod.getParameterTypes();
 		String[] sig = new String[paramClasses.length + 1];
 		String s = getSignatureType(pMethod.getReturnType());
@@ -118,7 +136,35 @@
 		return sig;
 	}
 
-	/** Returns a help string for the given method, which
+    /** Returns a help string for the given method, which
+     * is applied to the given class.
+     */
+    public static String getMethodHelp(Class pClass, Method[] pMethods) {
+        final List result = new ArrayList();
+        for (int i = 0;  i < pMethods.length;  i++) {
+            String help = getMethodHelp(pClass, pMethods[i]);
+            if (help != null) {
+                result.add(help);
+            }
+        }
+        switch (result.size()) {
+            case 0:
+                return null;
+            case 1:
+                return (String) result.get(0);
+            default:
+                StringBuffer sb = new StringBuffer();
+                for (int i = 0;  i < result.size();  i++) {
+                    sb.append(i+1);
+                    sb.append(": ");
+                    sb.append(result.get(i));
+                    sb.append("\n");
+                }
+                return sb.toString();
+        }
+    }
+
+    /** Returns a help string for the given method, which
 	 * is applied to the given class.
 	 */
 	public static String getMethodHelp(Class pClass, Method pMethod) {
@@ -138,4 +184,78 @@
 		sb.append(").");
 		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.
+     */
+    public static String getSignature(Object[] args) {
+        StringBuffer sb = new StringBuffer();
+        for (int i = 0;  i < args.length;  i++) {
+            if (i > 0) {
+                sb.append(", ");
+            }
+            if (args[i] == null) {
+                sb.append("null");
+            } else {
+                sb.append(args[i].getClass().getName());
+            }
+        }
+        return sb.toString();
+    }
 }

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=408757&r1=408756&r2=408757&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 Mon May 22 13:31:57 2006
@@ -91,6 +91,7 @@
     	if (pInstance == null) {
     		throw new NullPointerException("The object instance must not be null.");
     	}
+    	Map map = new HashMap();
         Method[] methods = pType.getMethods();
         for (int i = 0;  i < methods.length;  i++) {
             final Method method = methods[i];
@@ -107,9 +108,23 @@
                 continue;  // Ignore methods from Object.class
             }
             String name = pKey + "." + method.getName();
-            if (!pMap.containsKey(name)) {
-                pMap.put(name, newXmlRpcHandler(pType, pInstance, method));
+            Method[] mArray;
+            Method[] oldMArray = (Method[]) map.get(name);
+            if (oldMArray == null) {
+                mArray = new Method[]{method};
+            } else {
+                mArray = new Method[oldMArray.length+1];
+                System.arraycopy(oldMArray, 0, mArray, 0, oldMArray.length);
+                mArray[oldMArray.length] = method;
             }
+            map.put(name, mArray);
+        }
+
+        for (Iterator iter = map.entrySet().iterator();  iter.hasNext();  ) {
+            Map.Entry entry = (Map.Entry) iter.next();
+            String name = (String) entry.getKey();
+            Method[] mArray = (Method[]) entry.getValue();
+            pMap.put(name, newXmlRpcHandler(pType, pInstance, mArray));
         }
     }
 
@@ -120,33 +135,33 @@
      * @param pInstance The object, which is being invoked by
      * the created handler. Typically an instance of
      * <code>pClass</code>.
-     * @param pMethod The method being invoked.
+     * @param pMethods The method being invoked.
      */
     protected XmlRpcHandler newXmlRpcHandler(final Class pClass,
-    		final Object pInstance, final Method pMethod) {
+    		final Object pInstance, final Method[] pMethods) {
     	if (pInstance == null) {
     		throw new NullPointerException("The object instance must not be null.");
     	}
-    	String[] sig = getSignature(pMethod);
-    	String help = getMethodHelp(pClass, pMethod);
+    	String[][] sig = getSignature(pMethods);
+    	String help = getMethodHelp(pClass, pMethods);
     	if (sig == null  ||  help == null) {
-    		return new ReflectiveXmlRpcHandler(this, pClass, pInstance, pMethod);
+    		return new ReflectiveXmlRpcHandler(this, pClass, pInstance, pMethods);
     	}
     	return new ReflectiveXmlRpcMetaDataHandler(this, pClass, pInstance,
-    			pMethod, new String[][]{sig}, help);
+    			pMethods, sig, help);
     }
 
     /** Creates a signature for the given method.
      */
-    protected String[] getSignature(Method pMethod) {
-    	return Util.getSignature(pMethod);
+    protected String[][] getSignature(Method[] pMethods) {
+    	return Util.getSignature(pMethods);
     }
 
     /** Creates a help string for the given method, when applied
      * to the given class.
      */
-    protected String getMethodHelp(Class pClass, Method pMethod) {
-    	return Util.getMethodHelp(pClass, pMethod);
+    protected String getMethodHelp(Class pClass, Method[] pMethods) {
+    	return Util.getMethodHelp(pClass, pMethods);
     }
 
     /** Returns the {@link XmlRpcHandler} with the given name.

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=408757&r1=408756&r2=408757&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 Mon May 22 13:31:57 2006
@@ -22,6 +22,7 @@
 import org.apache.xmlrpc.XmlRpcHandler;
 import org.apache.xmlrpc.XmlRpcRequest;
 import org.apache.xmlrpc.common.XmlRpcNotAuthorizedException;
+import org.apache.xmlrpc.metadata.Util;
 import org.apache.xmlrpc.server.AbstractReflectiveHandlerMapping.AuthenticationHandler;
 
 
@@ -31,7 +32,7 @@
 	private final AbstractReflectiveHandlerMapping mapping;
 	private final Class clazz;
 	private final Object instance;
-	private final Method method;
+	private final Method[] methods;
 
 	/** Creates a new instance.
 	 * @param pMapping The mapping, which creates this handler.
@@ -41,15 +42,15 @@
 	 * messages only.
 	 * @param pInstance The instance, which will be invoked for
 	 * executing the handler.
-	 * @param pMethod The method, which will be invoked for
+	 * @param pMethods The method, which will be invoked for
 	 * executing the handler. 
 	 */
 	public ReflectiveXmlRpcHandler(AbstractReflectiveHandlerMapping pMapping,
-				Class pClass, Object pInstance, Method pMethod) {
+				Class pClass, Object pInstance, Method[] pMethods) {
 		mapping = pMapping;
 		clazz = pClass;
 		instance = pInstance;
-		method = pMethod;
+		methods = pMethods;
 	}
 
 	public Object execute(XmlRpcRequest pRequest) throws XmlRpcException {
@@ -61,20 +62,33 @@
 	    for (int j = 0;  j < args.length;  j++) {
 	        args[j] = pRequest.getParameter(j);
 	    }
-	    try {
-	        return method.invoke(instance, args);
+	    if (methods.length == 1) {
+            return invoke(methods[0], args);
+        } else {
+            for (int i = 0;  i < methods.length;  i++) {
+                if (Util.isMatching(methods[i], args)) {
+                    return invoke(methods[i], args);
+                }
+            }
+            throw new XmlRpcException("No method matching arguments: " + Util.getSignature(args));
+        }
+    }
+
+    private Object invoke(Method pMethod, Object[] pArgs) throws XmlRpcException {
+        try {
+	        return pMethod.invoke(instance, pArgs);
 	    } catch (IllegalAccessException e) {
 	        throw new XmlRpcException("Illegal access to method "
-	                                  + method.getName() + " in class "
+	                                  + pMethod.getName() + " in class "
 	                                  + clazz.getName(), e);
 	    } catch (IllegalArgumentException e) {
 	        throw new XmlRpcException("Illegal argument for method "
-	                                  + method.getName() + " in class "
+	                                  + pMethod.getName() + " in class "
 	                                  + clazz.getName(), e);
 	    } catch (InvocationTargetException e) {
 	        Throwable t = e.getTargetException();
 	        throw new XmlRpcException("Failed to invoke method "
-	                                  + method.getName() + " in class "
+	                                  + pMethod.getName() + " in class "
 	                                  + clazz.getName() + ": "
 	                                  + t.getMessage(), t);
 	    }



---------------------------------------------------------------------
To unsubscribe, e-mail: xmlrpc-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: xmlrpc-dev-help@ws.apache.org