Coverage Report - org.apache.xmlrpc.server.PropertyHandlerMapping
 
Classes in this File Line Coverage Branch Coverage Complexity
PropertyHandlerMapping
51% 
91% 
5,5
 
 1  1452
 /*
 2  
  * Copyright 1999,2005 The Apache Software Foundation.
 3  
  * 
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  * 
 8  
  *      http://www.apache.org/licenses/LICENSE-2.0
 9  
  * 
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.apache.xmlrpc.server;
 17  
 
 18  
 import java.io.File;
 19  
 import java.io.IOException;
 20  
 import java.lang.reflect.InvocationTargetException;
 21  
 import java.lang.reflect.Method;
 22  
 import java.lang.reflect.Modifier;
 23  
 import java.net.URL;
 24  
 import java.util.HashMap;
 25  
 import java.util.Iterator;
 26  
 import java.util.Map;
 27  
 import java.util.Properties;
 28  
 
 29  
 import org.apache.xmlrpc.XmlRpcException;
 30  
 import org.apache.xmlrpc.XmlRpcHandler;
 31  
 import org.apache.xmlrpc.XmlRpcRequest;
 32  
 
 33  
 
 34  
 /** A handler mapping based on a property file. The property file
 35  
  * contains a set of properties. The property key is taken as the
 36  
  * handler name. The property value is taken as the name of a
 37  
  * class being instantiated. For any non-void, non-static, and
 38  
  * public method in the class, an entry in the handler map is
 39  
  * generated.<br>
 40  
  * The following constrains apply to the classes:
 41  
  * <ol>
 42  
  *   <li>The classes must be stateless. In other words, any
 43  
  *     instance of the class must be completely thread safe.</li>
 44  
  * </ol>
 45  
  * A typical use would be, to specify interface names as the
 46  
  * property keys and implementations as the values.
 47  
  */
 48  
 public class PropertyHandlerMapping implements XmlRpcHandlerMapping {
 49  
         private final Map handlerMap;
 50  
 
 51  
         /** Creates a new instance, loading the property file
 52  
          * from the given URL.
 53  
          * @param pClassLoader Classloader being used to load the classes.
 54  
          * @param pURL The URL, from which the property file is being
 55  
          * loaded.
 56  
          * @throws IOException Loading the property file failed.
 57  
          * @throws XmlRpcException Initializing the handlers failed.
 58  
          */
 59  66
         public PropertyHandlerMapping(ClassLoader pClassLoader, URL pURL)
 60  
                         throws IOException, XmlRpcException {
 61  66
                 handlerMap = load(pClassLoader, pURL);
 62  66
         }
 63  
 
 64  
         /** Creates a new instance, loading the given property file.
 65  
          * @param pClassLoader Classloader being used to load the classes.
 66  
          * @param pFile File being loaded.
 67  
          * @throws IOException Loading the property file failed.
 68  
          * @throws XmlRpcException Initializing the handlers failed.
 69  
          */
 70  0
         public PropertyHandlerMapping(ClassLoader pClassLoader, File pFile)
 71  
                         throws IOException, XmlRpcException {
 72  0
                 handlerMap = load(pClassLoader, pFile.toURL());
 73  0
         }
 74  
 
 75  
         /** Creates a new instance, loading the properties from
 76  
          * the given resource.
 77  
          * @param pClassLoader Classloader being used to locate
 78  
          * the resource.
 79  
          * @param pResource Resource being loaded.
 80  
          * @throws IOException Loading the property file failed.
 81  
          * @throws XmlRpcException Initializing the handlers failed.
 82  
          */
 83  0
         public PropertyHandlerMapping(ClassLoader pClassLoader, String pResource)
 84  
                         throws IOException, XmlRpcException {
 85  0
                 URL url = pClassLoader.getResource(pResource);
 86  0
                 if (url == null) {
 87  0
                         throw new IOException("Unable to locate resource " + pResource);
 88  
                 }
 89  0
                 handlerMap = load(pClassLoader, url);
 90  0
         }
 91  
 
 92  
         private Map load(ClassLoader pClassLoader, URL pURL) throws IOException, XmlRpcException {
 93  66
                 Map map = new HashMap();
 94  66
                 Properties props = new Properties();
 95  66
                 props.load(pURL.openStream());
 96  198
                 for (Iterator iter = props.entrySet().iterator();  iter.hasNext();  ) {
 97  66
                         Map.Entry entry = (Map.Entry) iter.next();
 98  66
                         String key = (String) entry.getKey();
 99  66
                         String value = (String) entry.getValue();
 100  
                         final Class c;
 101  
                         try {
 102  66
                                 c = pClassLoader.loadClass(value);
 103  0
                         } catch (ClassNotFoundException e) {
 104  0
                                 throw new XmlRpcException("Unable to load class: " + value, e);
 105  
                         }
 106  66
                         if (c == null) {
 107  0
                                 throw new XmlRpcException(0, "Loading class " + value + " returned null.");
 108  
                         }
 109  
                         final Object o;
 110  
                         try {
 111  66
                                 o = c.newInstance();
 112  0
                         } catch (InstantiationException e) {
 113  0
                                 throw new XmlRpcException("Failed to instantiate class " + c.getName(), e);
 114  0
                         } catch (IllegalAccessException e) {
 115  0
                                 throw new XmlRpcException("Illegal access when instantiating class " + c.getName(), e);
 116  
                         }
 117  66
                         Method[] methods = c.getMethods();
 118  2112
                         for (int i = 0;  i < methods.length;  i++) {
 119  2046
                                 final Method method = methods[i];
 120  2046
                                 if (!Modifier.isPublic(method.getModifiers())) {
 121  0
                                         continue;  // Ignore methods, which aren't public
 122  
                                 }
 123  2046
                                 if (Modifier.isStatic(method.getModifiers())) {
 124  0
                                         continue;  // Ignore methods, which are static
 125  
                                 }
 126  2046
                                 if (method.getReturnType() == void.class) {
 127  330
                                         continue;  // Ignore void methods.
 128  
                                 }
 129  1716
                                 if (method.getDeclaringClass() == Object.class) {
 130  264
                                         continue;  // Ignore methods from Object.class
 131  
                                 }
 132  1452
                                 String name = key + "." + method.getName();
 133  1452
                                 if (!map.containsKey(name)) {
 134  1452
                                         map.put(name, new XmlRpcHandler(){
 135  
                                                 public Object execute(XmlRpcRequest pRequest) throws XmlRpcException {
 136  315
                                                         Object[] args = new Object[pRequest.getParameterCount()];
 137  630
                                                         for (int j = 0;  j < args.length;  j++) {
 138  315
                                                                 args[j] = pRequest.getParameter(j);
 139  
                                                         }
 140  
                                                         try {
 141  315
                                                                 return method.invoke(o, args);
 142  0
                                                         } catch (IllegalAccessException e) {
 143  0
                                                                 throw new XmlRpcException("Illegal access to method "
 144  0
                                                                                                                   + method.getName() + " in class "
 145  0
                                                                                                                   + c.getName(), e);
 146  0
                                                         } catch (IllegalArgumentException e) {
 147  0
                                                                 throw new XmlRpcException("Illegal argument for method "
 148  0
                                                                                                                   + method.getName() + " in class "
 149  0
                                                                                                                   + c.getName(), e);
 150  0
                                                         } catch (InvocationTargetException e) {
 151  0
                                                                 Throwable t = e.getTargetException();
 152  0
                                                                 throw new XmlRpcException("Failed to invoke method "
 153  0
                                                                                                                   + method.getName() + " in class "
 154  0
                                                                                                                   + c.getName() + ": "
 155  0
                                                                                                                   + t.getMessage(), t);
 156  
                                                         }
 157  
                                                 }
 158  
                                         });
 159  
                                 }
 160  
                         }
 161  
                 }
 162  66
                 return map;
 163  
         }
 164  
 
 165  
         public XmlRpcHandler getHandler(String handlerName)
 166  
                         throws XmlRpcNoSuchHandlerException, XmlRpcException {
 167  315
                 XmlRpcHandler result = (XmlRpcHandler) handlerMap.get(handlerName);
 168  315
                 if (result == null) {
 169  0
                         throw new XmlRpcNoSuchHandlerException("No such handler: " + handlerName);
 170  
                 }
 171  315
                 return result;
 172  
         }
 173  
 }