View Javadoc
1 /*** 2 * Redistribution and use of this software and associated documentation 3 * ("Software"), with or without modification, are permitted provided 4 * that the following conditions are met: 5 * 6 * 1. Redistributions of source code must retain copyright 7 * statements and notices. Redistributions must also contain a 8 * copy of this document. 9 * 10 * 2. Redistributions in binary form must reproduce the 11 * above copyright notice, this list of conditions and the 12 * following disclaimer in the documentation and/or other 13 * materials provided with the distribution. 14 * 15 * 3. The name "Exolab" must not be used to endorse or promote 16 * products derived from this Software without prior written 17 * permission of Exoffice Technologies. For written permission, 18 * please contact tma@netspace.net.au. 19 * 20 * 4. Products derived from this Software may not be called "Exolab" 21 * nor may "Exolab" appear in their names without prior written 22 * permission of Exoffice Technologies. Exolab is a registered 23 * trademark of Exoffice Technologies. 24 * 25 * 5. Due credit should be given to the Exolab Project 26 * (http://www.exolab.org/). 27 * 28 * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS 29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT 30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 32 * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 39 * OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 * Copyright 2001-2004 (C) Exoffice Technologies Inc. All Rights Reserved. 42 * 43 * $Id: ClassHelper.java,v 1.3 2004/01/31 13:44:24 tanderson Exp $ 44 */ 45 package org.exolab.jmscts.core; 46 47 import java.lang.reflect.InvocationTargetException; 48 import java.lang.reflect.Method; 49 import java.lang.reflect.Modifier; 50 import java.util.ArrayList; 51 52 import org.exolab.jmscts.core.types.PropertyTypeType; 53 54 55 /*** 56 * Helper for loading classes and setting/getting any public properties. 57 * 58 * @version $Revision: 1.3 $ $Date: 2004/01/31 13:44:24 $ 59 * @author <a href="mailto:tma@netspace.net.au">Tim Anderson</a> 60 */ 61 public final class ClassHelper { 62 63 64 /*** 65 * A map of objectified primitive types, and their corresponding primitive 66 * types 67 */ 68 private static final Class[][] TYPES = { 69 {Boolean.class, boolean.class}, {Byte.class, byte.class}, 70 {Short.class, short.class}, {Character.class, char.class}, 71 {Integer.class, int.class}, {Long.class, long.class}, 72 {Float.class, float.class}, {Double.class, double.class}}; 73 74 75 /*** 76 * Prevent construction of utility class 77 */ 78 private ClassHelper() { 79 } 80 81 /*** 82 * Create a new instance of an object identified by its class name, 83 * and set its properties 84 * 85 * @param className the name of the class 86 * @param properties the list of properties to set 87 * @return a new instance the specified class 88 * @throws ClassNotFoundException if the class cannot be located 89 * @throws IllegalAccessException if the class or initializer is not 90 * accessible 91 * @throws InstantiationException if the instantiation fails 92 * @throws InvocationTargetException if the underlying method throws an 93 * exception 94 * @throws NoSuchMethodException if a matching method is not found 95 */ 96 public static Object instantiate(String className, 97 Property[] properties) 98 throws ClassNotFoundException, IllegalAccessException, 99 InstantiationException, InvocationTargetException, 100 NoSuchMethodException { 101 102 Object object = Class.forName(className).newInstance(); 103 for (int i = 0; i < properties.length; ++i) { 104 Property property = properties[i]; 105 Class type = Class.forName(property.getType().toString()); 106 Class[] types = new Class[] {type}; 107 String name = "set" + property.getName(); 108 Method method = object.getClass().getMethod(name, types); 109 Object arg = PropertyHelper.create(property); 110 Object[] args = new Object[]{arg}; 111 method.invoke(object, args); 112 } 113 return object; 114 } 115 116 /*** 117 * Helper to returns the properties of an object 118 * 119 * @param object the object to retrieve properties for 120 * @return the set of properties of object 121 * @throws IllegalAccessException if the class or initializer is not 122 * accessible 123 * @throws InvocationTargetException if the underlying method throws an 124 * exception 125 */ 126 public static Property[] getProperties(Object object) 127 throws IllegalAccessException, InvocationTargetException { 128 final String prefix = "get"; 129 130 ArrayList result = new ArrayList(); 131 Method[] methods = object.getClass().getDeclaredMethods(); 132 for (int i = 0; i < methods.length; ++i) { 133 Method method = methods[i]; 134 int modifier = method.getModifiers(); 135 if (method.getParameterTypes().length == 0 136 && Modifier.isPublic(modifier) && !Modifier.isStatic(modifier) 137 && method.getName().startsWith(prefix)) { 138 139 Class type = method.getReturnType(); 140 if (type.equals(Boolean.class) 141 || type.equals(Short.class) 142 || type.equals(Integer.class) 143 || type.equals(Long.class) 144 || type.equals(Float.class) 145 || type.equals(Double.class) 146 || type.equals(String.class)) { 147 Property property = new Property(); 148 String name = method.getName().substring(prefix.length()); 149 property.setName(name); 150 property.setType(PropertyTypeType.valueOf(type.getName())); 151 Object value = method.invoke(object, new Object[]{}); 152 property.setValue(value.toString()); 153 result.add(property); 154 } 155 } 156 } 157 return (Property[]) result.toArray(new Property[]{}); 158 } 159 160 /*** 161 * Helper to return a method given its name and a list of arguments 162 * 163 * @param type the class to locate the method on 164 * @param name the method name 165 * @param args the list of arguments to match against, or null if the 166 * method takes no arguments 167 * @return the method matching the name and list of arguments 168 * @throws NoSuchMethodException if the method cannot be found 169 */ 170 public static Method getMethod(Class type, String name, Object[] args) 171 throws NoSuchMethodException { 172 173 boolean containsNull = false; 174 Class[] types = null; 175 if (args != null) { 176 types = new Class[args.length]; 177 for (int i = 0; i < args.length; ++i) { 178 if (args[i] != null) { 179 types[i] = args[i].getClass(); 180 } else { 181 containsNull = true; 182 } 183 } 184 } else { 185 types = new Class[]{}; 186 } 187 188 Method method = null; 189 if (!containsNull) { 190 try { 191 // try a direct lookup 192 method = type.getMethod(name, types); 193 } catch (NoSuchMethodException ignore) { 194 if (types.length != 0) { 195 // try converting any objectified types to primitives 196 Class[] converted = new Class[types.length]; 197 for (int i = 0; i < args.length; ++i) { 198 converted[i] = getPrimitiveType(args[i].getClass()); 199 } 200 try { 201 method = type.getMethod(name, types); 202 } catch (NoSuchMethodException ignore2) { 203 // no-op 204 } 205 } 206 } 207 } 208 if (method == null) { 209 // try and find it iteratively, using the class' public declared 210 // methods 211 Method[] methods = type.getDeclaredMethods(); 212 for (int i = 0; i < methods.length; ++i) { 213 if (Modifier.isPublic(methods[i].getModifiers()) 214 && methods[i].getName().equals(name)) { 215 if (checkParameters(methods[i], types)) { 216 method = methods[i]; 217 break; 218 } 219 } 220 } 221 if (method == null) { 222 // try and find it iteratively, using the MUCH slower 223 // getMethods() method 224 methods = type.getMethods(); 225 for (int i = 0; i < methods.length; ++i) { 226 if (methods[i].getName().equals(name)) { 227 if (checkParameters(methods[i], types)) { 228 method = methods[i]; 229 break; 230 } 231 } 232 } 233 } 234 if (method == null) { 235 String msg = "No method found for name=" + name 236 + ", argument types=("; 237 if (args != null && args.length > 0) { 238 for (int i = 0; i < args.length; ++i) { 239 if (i > 0) { 240 msg += ", "; 241 } 242 if (args[i] != null) { 243 msg += args[i].getClass().getName(); 244 } else { 245 msg += "Object"; 246 } 247 } 248 } 249 msg += ")"; 250 251 throw new NoSuchMethodException(msg); 252 } 253 } 254 return method; 255 } 256 257 /*** 258 * Helper to return the primitive type associated with an object wrapper 259 * type 260 * 261 * @param wrapper the object wrapper class 262 * @return the associated primitive type, or the wrapper type, if there 263 * is no associated primitive type 264 */ 265 public static Class getPrimitiveType(Class wrapper) { 266 Class result = null; 267 for (int i = 0; i < TYPES.length; ++i) { 268 if (wrapper.equals(TYPES[i][0])) { 269 result = TYPES[i][1]; 270 break; 271 } 272 } 273 274 return (result != null) ? result : wrapper; 275 } 276 277 /*** 278 * Helper to return the primitive type name associated with an object 279 * wrapper type 280 * 281 * @param wrapper the object wrapper class 282 * @return the associated primitive type name, or the wrapper type name, 283 * if there is no associated primitive type. Array types are returned 284 * in the form '<class>[]' 285 */ 286 public static String getPrimitiveName(Class wrapper) { 287 String result = null; 288 Class type = getPrimitiveType(wrapper); 289 if (type.isArray()) { 290 result = type.getComponentType().getName() + "[]"; 291 } else { 292 result = type.getName(); 293 } 294 return result; 295 } 296 297 /*** 298 * Helper to determine if a list of argument types match that of 299 * a method 300 * 301 * @param method the method to check 302 * @param types the argument types 303 * @return <code>true</code> if the argument types are compatible 304 */ 305 private static boolean checkParameters(Method method, Class[] types) { 306 boolean result = true; 307 Class[] parameters = method.getParameterTypes(); 308 if (parameters.length != types.length) { 309 result = false; 310 } else { 311 for (int i = 0; i < parameters.length; ++i) { 312 Class parameter = parameters[i]; 313 if (types[i] == null) { 314 if (parameter.isPrimitive()) { 315 result = false; 316 break; 317 } 318 } else if (!parameter.isAssignableFrom(types[i]) 319 && !parameter.isAssignableFrom( 320 getPrimitiveType(types[i]))) { 321 result = false; 322 break; 323 } 324 } 325 } 326 return result; 327 } 328 329 }

This page was automatically generated by Maven