Author: jochen
Date: Fri Feb 24 04:57:18 2006
New Revision: 380660

URL: http://svn.apache.org/viewcvs?rev=380660&view=rev
Log:
Accepted patch from XMLRPC-76.

Added:
    
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
Modified:
    
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/PropertyHandlerMapping.java
    webservices/xmlrpc/trunk/src/changes/changes.xml

Added: 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/AbstractReflectiveHandlerMapping.java
URL: 
http://svn.apache.org/viewcvs/webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/AbstractReflectiveHandlerMapping.java?rev=380660&view=auto
==============================================================================
--- 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/AbstractReflectiveHandlerMapping.java
 (added)
+++ 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/AbstractReflectiveHandlerMapping.java
 Fri Feb 24 04:57:18 2006
@@ -0,0 +1,153 @@
+package org.apache.xmlrpc.server;
+
+import org.apache.xmlrpc.XmlRpcRequest;
+import org.apache.xmlrpc.XmlRpcException;
+import org.apache.xmlrpc.XmlRpcHandler;
+import org.apache.xmlrpc.common.XmlRpcNotAuthorizedException;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.InvocationTargetException;
+
+
+/** Abstract base class of handler mappings, which are
+ * using reflection.
+ */
+public abstract class AbstractReflectiveHandlerMapping implements 
XmlRpcHandlerMapping {
+    /** An object implementing this interface may be used
+     * to validate user names and passwords.
+     */
+    public interface AuthenticationHandler {
+        /** Returns, whether the user is authenticated and
+         * authorized to perform the request.
+         */
+        boolean isAuthorized(XmlRpcRequest pRequest)
+            throws XmlRpcException;
+    }
+
+    protected Map handlerMap = new HashMap();
+    private AuthenticationHandler authenticationHandler;
+
+    /** Returns the authentication handler, if any, or null.
+     */
+    public AuthenticationHandler getAuthenticationHandler() {
+        return authenticationHandler;
+    }
+
+    /** Sets the authentication handler, if any, or null.
+     */
+    public void setAuthenticationHandler(
+            AuthenticationHandler pAuthenticationHandler) {
+        authenticationHandler = pAuthenticationHandler;
+    }
+
+    /** Searches for methods in the given class. For any valid
+     * method, it creates an instance of [EMAIL PROTECTED] XmlRpcHandler}.
+     * Valid methods are defined as follows:
+     * <ul>
+     *   <li>They must be public.</li>
+     *   <li>They must not be static.</li>
+     *   <li>The return type must not be void.</li>
+     *   <li>The declaring class must not be
+     *     [EMAIL PROTECTED] java.lang.Object}.</li>
+     *   <li>If multiple methods with the same name exist,
+     *     which meet the above conditins, then only the
+     *     first method is valid.</li>
+     * </ul>
+     * @param pMap Handler map, in which created handlers are
+     * being registered.
+     * @param pKey Suffix for building handler names. A dot and
+     * the method name are being added.
+     * @param pType The class being inspected.
+     * @param pInstance The object being invoked. Note, that this
+     * object must be stateless: Multiple threads can run on it
+     * at the same time.
+     */
+    protected void registerPublicMethods(Map pMap, String pKey,
+               Class pType, Object pInstance) {
+       if (pInstance == null) {
+               throw new NullPointerException("The object instance must not be 
null.");
+       }
+        Method[] methods = pType.getMethods();
+        for (int i = 0;  i < methods.length;  i++) {
+            final Method method = methods[i];
+            if (!Modifier.isPublic(method.getModifiers())) {
+                continue;  // Ignore methods, which aren't public
+            }
+            if (Modifier.isStatic(method.getModifiers())) {
+                continue;  // Ignore methods, which are static
+            }
+            if (method.getReturnType() == void.class) {
+                continue;  // Ignore void methods.
+            }
+            if (method.getDeclaringClass() == Object.class) {
+                continue;  // Ignore methods from Object.class
+            }
+            String name = pKey + "." + method.getName();
+            if (!pMap.containsKey(name)) {
+                pMap.put(name, newXmlRpcHandler(pType, pInstance, method));
+            }
+        }
+    }
+
+    /** Creates a new instance of [EMAIL PROTECTED] XmlRpcHandler}.
+     * @param pClass The class, which was inspected for handler
+     * methods. This is used for error messages only. Typically,
+     * it is the same than <pre>pInstance.getClass()</pre>.
+     * @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.
+     */
+    protected XmlRpcHandler newXmlRpcHandler(final Class pClass,
+               final Object pInstance, final Method pMethod) {
+       if (pInstance == null) {
+               throw new NullPointerException("The object instance must not be 
null.");
+       }
+       return new XmlRpcHandler(){
+            public Object execute(XmlRpcRequest pRequest) throws 
XmlRpcException {
+                AuthenticationHandler authHandler = getAuthenticationHandler();
+                if (authHandler != null  &&  
!authHandler.isAuthorized(pRequest)) {
+                    throw new XmlRpcNotAuthorizedException("Not authorized");
+                }
+                Object[] args = new Object[pRequest.getParameterCount()];
+                for (int j = 0;  j < args.length;  j++) {
+                    args[j] = pRequest.getParameter(j);
+                }
+                try {
+                    return pMethod.invoke(pInstance, args);
+                } catch (IllegalAccessException e) {
+                    throw new XmlRpcException("Illegal access to method "
+                                              + pMethod.getName() + " in class 
"
+                                              + pClass.getName(), e);
+                } catch (IllegalArgumentException e) {
+                    throw new XmlRpcException("Illegal argument for method "
+                                              + pMethod.getName() + " in class 
"
+                                              + pClass.getName(), e);
+                } catch (InvocationTargetException e) {
+                    Throwable t = e.getTargetException();
+                    throw new XmlRpcException("Failed to invoke method "
+                                              + pMethod.getName() + " in class 
"
+                                              + pClass.getName() + ": "
+                                              + t.getMessage(), t);
+                }
+            }
+        };
+    }
+
+    /** Returns the [EMAIL PROTECTED] XmlRpcHandler} with the given name.
+     * @param pHandlerName The handlers name
+     * @throws XmlRpcNoSuchHandlerException A handler with the given
+     * name is unknown.
+     */
+    public XmlRpcHandler getHandler(String pHandlerName)
+            throws XmlRpcNoSuchHandlerException, XmlRpcException {
+        XmlRpcHandler result = (XmlRpcHandler) handlerMap.get(pHandlerName);
+        if (result == null) {
+            throw new XmlRpcNoSuchHandlerException("No such handler: " + 
pHandlerName);
+        }
+        return result;
+    }
+}

Added: 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/DynamicHandlerMapping.java
URL: 
http://svn.apache.org/viewcvs/webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/DynamicHandlerMapping.java?rev=380660&view=auto
==============================================================================
--- 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/DynamicHandlerMapping.java
 (added)
+++ 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/DynamicHandlerMapping.java
 Fri Feb 24 04:57:18 2006
@@ -0,0 +1,29 @@
+package org.apache.xmlrpc.server;
+
+import java.util.Iterator;
+
+
+/** A handler mapping, which requires explicit registration
+ * of handlers.
+ */
+public class DynamicHandlerMapping extends AbstractReflectiveHandlerMapping {
+       /** Adds handlers for the given object to the mapping.
+        * The handlers are build by invoking
+        * [EMAIL PROTECTED] #registerPublicMethods(java.util.Map, String, 
Class, Object)}.
+        * @param pKey The class key, which is passed
+        * to [EMAIL PROTECTED] #registerPublicMethods(java.util.Map, String, 
Class, Object)}.
+        * @param pHandler The object, which is handling requests.
+        */
+    public void addHandler(String pKey, Object pHandler) {
+        registerPublicMethods(handlerMap, pKey, pHandler.getClass(), pHandler);
+    }
+
+    /** Removes all handlers with the given class key.
+     */
+    public void removeHandler(String pKey) {
+        for (Iterator i = handlerMap.keySet().iterator(); i.hasNext();) {
+            String k = (String)i.next();
+            if (k.startsWith(pKey)) i.remove();
+        }
+    }
+}

Modified: 
webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/PropertyHandlerMapping.java
URL: 
http://svn.apache.org/viewcvs/webservices/xmlrpc/trunk/server/src/main/java/org/apache/xmlrpc/server/PropertyHandlerMapping.java?rev=380660&r1=380659&r2=380660&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 Feb 24 04:57:18 2006
@@ -15,11 +15,7 @@
  */
 package org.apache.xmlrpc.server;
 
-import java.io.File;
 import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
 import java.net.URL;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -27,10 +23,6 @@
 import java.util.Properties;
 
 import org.apache.xmlrpc.XmlRpcException;
-import org.apache.xmlrpc.XmlRpcHandler;
-import org.apache.xmlrpc.XmlRpcRequest;
-import org.apache.xmlrpc.common.XmlRpcHttpRequestConfig;
-import org.apache.xmlrpc.common.XmlRpcNotAuthorizedException;
 
 
 /** A handler mapping based on a property file. The property file
@@ -47,162 +39,64 @@
  * A typical use would be, to specify interface names as the
  * property keys and implementations as the values.
  */
-public class PropertyHandlerMapping implements XmlRpcHandlerMapping {
-       /** An object implementing this interface may be used
-        * to validate user names and passwords.
-        */
-       public interface AuthenticationHandler {
-               /** Returns, whether the user is authenticated and
-                * authorized to perform the request.
-                */
-               boolean isAuthorized(XmlRpcRequest pRequest)
-                       throws XmlRpcException;
-       }
-
-       private final Map handlerMap;
-       private AuthenticationHandler authenticationHandler;
-
-       /** Creates a new instance, loading the property file
-        * from the given URL.
-        * @param pClassLoader Classloader being used to load the classes.
-        * @param pURL The URL, from which the property file is being
-        * loaded.
-        * @throws IOException Loading the property file failed.
-        * @throws XmlRpcException Initializing the handlers failed.
-        */
-       public PropertyHandlerMapping(ClassLoader pClassLoader, URL pURL)
-                       throws IOException, XmlRpcException {
-               handlerMap = load(pClassLoader, pURL);
-       }
-
-       /** Creates a new instance, loading the given property file.
-        * @param pClassLoader Classloader being used to load the classes.
-        * @param pFile File being loaded.
-        * @throws IOException Loading the property file failed.
-        * @throws XmlRpcException Initializing the handlers failed.
-        */
-       public PropertyHandlerMapping(ClassLoader pClassLoader, File pFile)
-                       throws IOException, XmlRpcException {
-               handlerMap = load(pClassLoader, pFile.toURL());
-       }
-
-       /** Creates a new instance, loading the properties from
-        * the given resource.
-        * @param pClassLoader Classloader being used to locate
-        * the resource.
-        * @param pResource Resource being loaded.
-        * @throws IOException Loading the property file failed.
-        * @throws XmlRpcException Initializing the handlers failed.
-        */
-       public PropertyHandlerMapping(ClassLoader pClassLoader, String 
pResource)
-                       throws IOException, XmlRpcException {
-               URL url = pClassLoader.getResource(pResource);
-               if (url == null) {
-                       throw new IOException("Unable to locate resource " + 
pResource);
-               }
-               handlerMap = load(pClassLoader, url);
-       }
-
-       /** Returns the authentication handler, if any, or null.
-        */
-       public AuthenticationHandler getAuthenticationHandler() {
-               return authenticationHandler;
-       }
-
-       /** Sets the authentication handler, if any, or null.
-        */
-       public void setAuthenticationHandler(
-                       AuthenticationHandler pAuthenticationHandler) {
-               authenticationHandler = pAuthenticationHandler;
-       }
-
-       private Map load(ClassLoader pClassLoader, URL pURL) throws 
IOException, XmlRpcException {
-               Map map = new HashMap();
-               Properties props = new Properties();
-               props.load(pURL.openStream());
-               for (Iterator iter = props.entrySet().iterator();  
iter.hasNext();  ) {
-                       Map.Entry entry = (Map.Entry) iter.next();
-                       String key = (String) entry.getKey();
-                       String value = (String) entry.getValue();
-                       final Class c;
-                       try {
-                               c = pClassLoader.loadClass(value);
-                       } catch (ClassNotFoundException e) {
-                               throw new XmlRpcException("Unable to load 
class: " + value, e);
-                       }
-                       if (c == null) {
-                               throw new XmlRpcException(0, "Loading class " + 
value + " returned null.");
-                       }
-                       final Object o;
-                       try {
-                               o = c.newInstance();
-                       } catch (InstantiationException e) {
-                               throw new XmlRpcException("Failed to 
instantiate class " + c.getName(), e);
-                       } catch (IllegalAccessException e) {
-                               throw new XmlRpcException("Illegal access when 
instantiating class " + c.getName(), e);
-                       }
-                       Method[] methods = c.getMethods();
-                       for (int i = 0;  i < methods.length;  i++) {
-                               final Method method = methods[i];
-                               if (!Modifier.isPublic(method.getModifiers())) {
-                                       continue;  // Ignore methods, which 
aren't public
-                               }
-                               if (Modifier.isStatic(method.getModifiers())) {
-                                       continue;  // Ignore methods, which are 
static
-                               }
-                               if (method.getReturnType() == void.class) {
-                                       continue;  // Ignore void methods.
-                               }
-                               if (method.getDeclaringClass() == Object.class) 
{
-                                       continue;  // Ignore methods from 
Object.class
-                               }
-                               String name = key + "." + method.getName();
-                               if (!map.containsKey(name)) {
-                                       map.put(name, newXmlRpcHandler(c, o, 
method));
-                               }
-                       }
-               }
-               return map;
-       }
-
-       protected XmlRpcHandler newXmlRpcHandler(final Class pClass, final 
Object pValue, final Method pMethod) {
-               return new XmlRpcHandler(){
-                       public Object execute(XmlRpcRequest pRequest) throws 
XmlRpcException {
-                               AuthenticationHandler authHandler = 
getAuthenticationHandler();
-                               if (authHandler != null  &&  
!authHandler.isAuthorized(pRequest)) {
-                                       throw new 
XmlRpcNotAuthorizedException("Not authorized");
-                               }
-                               Object[] args = new 
Object[pRequest.getParameterCount()];
-                               for (int j = 0;  j < args.length;  j++) {
-                                       args[j] = pRequest.getParameter(j);
-                               }
-                               try {
-                                       return pMethod.invoke(pValue, args);
-                               } catch (IllegalAccessException e) {
-                                       throw new XmlRpcException("Illegal 
access to method "
-                                                                               
          + pMethod.getName() + " in class "
-                                                                               
          + pClass.getName(), e);
-                               } catch (IllegalArgumentException e) {
-                                       throw new XmlRpcException("Illegal 
argument for method "
-                                                                               
          + pMethod.getName() + " in class "
-                                                                               
          + pClass.getName(), e);
-                               } catch (InvocationTargetException e) {
-                                       Throwable t = e.getTargetException();
-                                       throw new XmlRpcException("Failed to 
invoke method "
-                                                                               
          + pMethod.getName() + " in class "
-                                                                               
          + pClass.getName() + ": "
-                                                                               
          + t.getMessage(), t);
-                               }
-                       }
-               };
-       }
-
-       public XmlRpcHandler getHandler(String handlerName)
-                       throws XmlRpcNoSuchHandlerException, XmlRpcException {
-               XmlRpcHandler result = (XmlRpcHandler) 
handlerMap.get(handlerName);
-               if (result == null) {
-                       throw new XmlRpcNoSuchHandlerException("No such 
handler: " + handlerName);
-               }
-               return result;
-       }
+public class PropertyHandlerMapping extends AbstractReflectiveHandlerMapping {
+    /** Creates a new instance, loading the property file
+     * from the given URL.
+     * @param pClassLoader Classloader being used to load the classes.
+     * @param pURL The URL, from which the property file is being
+     * loaded.
+     * @throws IOException Loading the property file failed.
+     * @throws XmlRpcException Initializing the handlers failed.
+     */
+    public PropertyHandlerMapping(ClassLoader pClassLoader, URL pURL)
+            throws IOException, XmlRpcException {
+        handlerMap = load(pClassLoader, pURL);
+    }
+
+    /** Creates a new instance, loading the properties from
+     * the given resource.
+     * @param pClassLoader Classloader being used to locate
+     * the resource.
+     * @param pResource Resource being loaded.
+     * @throws IOException Loading the property file failed.
+     * @throws XmlRpcException Initializing the handlers failed.
+     */
+    public PropertyHandlerMapping(ClassLoader pClassLoader, String pResource)
+            throws IOException, XmlRpcException {
+        URL url = pClassLoader.getResource(pResource);
+        if (url == null) {
+            throw new IOException("Unable to locate resource " + pResource);
+        }
+        handlerMap = load(pClassLoader, url);
+    }
+
+    private Map load(ClassLoader pClassLoader, URL pURL) throws IOException, 
XmlRpcException {
+        Map map = new HashMap();
+        Properties props = new Properties();
+        props.load(pURL.openStream());
+        for (Iterator iter = props.entrySet().iterator();  iter.hasNext();  ) {
+            Map.Entry entry = (Map.Entry) iter.next();
+            String key = (String) entry.getKey();
+            String value = (String) entry.getValue();
+            final Class c;
+            try {
+                c = pClassLoader.loadClass(value);
+            } catch (ClassNotFoundException e) {
+                throw new XmlRpcException("Unable to load class: " + value, e);
+            }
+            if (c == null) {
+                throw new XmlRpcException(0, "Loading class " + value + " 
returned null.");
+            }
+            final Object o;
+            try {
+                o = c.newInstance();
+            } catch (InstantiationException e) {
+                throw new XmlRpcException("Failed to instantiate class " + 
c.getName(), e);
+            } catch (IllegalAccessException e) {
+                throw new XmlRpcException("Illegal access when instantiating 
class " + c.getName(), e);
+            }
+            registerPublicMethods(map, key, c, o);
+        }
+        return map;
+    }
 }

Modified: webservices/xmlrpc/trunk/src/changes/changes.xml
URL: 
http://svn.apache.org/viewcvs/webservices/xmlrpc/trunk/src/changes/changes.xml?rev=380660&r1=380659&r2=380660&view=diff
==============================================================================
--- webservices/xmlrpc/trunk/src/changes/changes.xml (original)
+++ webservices/xmlrpc/trunk/src/changes/changes.xml Fri Feb 24 04:57:18 2006
@@ -12,6 +12,11 @@
           due-to-email="[EMAIL PROTECTED]">
           The "string" tag could not be parsed.
       </action>
+      <action dev="jochen" type="enhancement" due-to="Walter Mundt"
+          due-to-email="[EMAIL PROTECTED]"
+          issue="XMLRPC76">
+                 Added the DynamicHandlerMapping.
+      </action>
       <action dev="jochen" type="enhancement">
         The project is now splitted into three jar files:
         common, client, and server.


Reply via email to