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.