1 7 package java.beans; 8 9 import java.lang.reflect.Constructor ; 10 import java.lang.reflect.Field ; 11 import java.lang.reflect.Method ; 12 import java.lang.reflect.Modifier ; 13 14 import java.lang.ref.Reference ; 15 import java.lang.ref.SoftReference ; 16 17 import java.util.*; 18 19 import com.sun.beans.ObjectHandler; 20 import sun.reflect.misc.MethodUtil; 21 import sun.reflect.misc.ConstructorUtil; 22 import sun.reflect.misc.ReflectUtil; 23 24 28 class ReflectionUtils { 29 30 private static Reference methodCacheRef; 31 32 public static Class typeToClass(Class type) { 33 return type.isPrimitive() ? ObjectHandler.typeNameToClass(type.getName()) : type; 34 } 35 36 public static boolean isPrimitive(Class type) { 37 return primitiveTypeFor(type) != null; 38 } 39 40 public static Class primitiveTypeFor(Class wrapper) { 41 if (wrapper == Boolean .class) return Boolean.TYPE; 42 if (wrapper == Byte .class) return Byte.TYPE; 43 if (wrapper == Character .class) return Character.TYPE; 44 if (wrapper == Short .class) return Short.TYPE; 45 if (wrapper == Integer .class) return Integer.TYPE; 46 if (wrapper == Long .class) return Long.TYPE; 47 if (wrapper == Float .class) return Float.TYPE; 48 if (wrapper == Double .class) return Double.TYPE; 49 if (wrapper == Void .class) return Void.TYPE; 50 return null; 51 } 52 53 61 private static boolean matchArguments(Class [] argClasses, Class [] argTypes) { 62 return matchArguments(argClasses, argTypes, false); 63 } 64 65 73 private static boolean matchExplicitArguments(Class [] argClasses, Class [] argTypes) { 74 return matchArguments(argClasses, argTypes, true); 75 } 76 77 private static boolean matchArguments(Class [] argClasses, 78 Class [] argTypes, boolean explicit) { 79 80 boolean match = (argClasses.length == argTypes.length); 81 for(int j = 0; j < argClasses.length && match; j++) { 82 Class argType = argTypes[j]; 83 if (argType.isPrimitive()) { 84 argType = typeToClass(argType); 85 } 86 if (explicit) { 87 if (argClasses[j] != argType) { 89 match = false; 90 } 91 } else { 92 if (argClasses[j] != null && 94 !(argType.isAssignableFrom(argClasses[j]))) { 95 match = false; 96 } 97 } 98 } 99 return match; 100 } 101 102 106 static Method getPublicMethod(Class declaringClass, String methodName, 107 Class [] argClasses) throws NoSuchMethodException { 108 Method m; 109 110 m = findPublicMethod(declaringClass, methodName, argClasses); 111 if (m == null) 112 throw new NoSuchMethodException (declaringClass.getName() + "." + methodName); 113 return m; 114 } 115 116 120 public static Method findPublicMethod(Class declaringClass, String methodName, 121 Class [] argClasses) { 122 if (argClasses.length == 0) { 126 try { 127 return MethodUtil.getMethod(declaringClass, methodName, argClasses); 128 } 129 catch (NoSuchMethodException e) { 130 return null; 131 } catch (SecurityException se) { 132 } 134 } 135 Method [] methods = MethodUtil.getPublicMethods(declaringClass); 136 List list = new ArrayList(); 137 for(int i = 0; i < methods.length; i++) { 138 Method method = methods[i]; 140 if (method.getName().equals(methodName)) { 141 if (matchArguments(argClasses, method.getParameterTypes())) { 142 list.add(method); 143 } 144 } 145 } 146 if (list.size() > 0) { 147 if (list.size() == 1) { 148 return (Method )list.get(0); 149 } 150 else { 151 ListIterator iterator = list.listIterator(); 152 Method method; 153 while (iterator.hasNext()) { 154 method = (Method )iterator.next(); 155 if (matchExplicitArguments(argClasses, method.getParameterTypes())) { 156 return method; 157 } 158 } 159 return getMostSpecificMethod(list, argClasses); 162 } 163 } 164 return null; 165 } 166 167 181 private static Method getMostSpecificMethod(List methods, Class [] args) { 182 Method method = null; 183 184 int matches = 0; 185 int lastMatch = matches; 186 187 ListIterator iterator = methods.listIterator(); 188 while (iterator.hasNext()) { 189 Method m = (Method )iterator.next(); 190 Class [] mArgs = m.getParameterTypes(); 191 matches = 0; 192 for (int i = 0; i < args.length; i++) { 193 Class mArg = mArgs[i]; 194 if (mArg.isPrimitive()) { 195 mArg = typeToClass(mArg); 196 } 197 if (args[i] == mArg) { 198 matches++; 199 } 200 } 201 if (matches == 0 && lastMatch == 0) { 202 if (method == null) { 203 method = m; 204 } else { 205 if (!matchArguments(method.getParameterTypes(), 210 m.getParameterTypes())) { 211 method = m; 212 } 213 } 214 } else if (matches > lastMatch) { 215 lastMatch = matches; 216 method = m; 217 } else if (matches == lastMatch) { 218 method = null; 220 } 221 } 222 return method; 223 } 224 225 228 public static Method findMethod(Class targetClass, String methodName, 229 Class [] argClasses) { 230 Method m = findPublicMethod(targetClass, methodName, argClasses); 231 if (m != null && Modifier.isPublic(m.getDeclaringClass().getModifiers())) { 232 return m; 233 } 234 235 264 for(Class type = targetClass; type != null; type = type.getSuperclass()) { 265 Class [] interfaces = type.getInterfaces(); 266 for(int i = 0; i < interfaces.length; i++) { 267 m = findPublicMethod(interfaces[i], methodName, argClasses); 268 if (m != null) { 269 return m; 270 } 271 } 272 } 273 return null; 274 } 275 276 280 private static class Signature { 281 private Class targetClass; 282 private String methodName; 283 private Class [] argClasses; 284 285 private volatile int hashCode = 0; 286 287 public Signature(Class targetClass, String methodName, Class [] argClasses) { 288 this.targetClass = targetClass; 289 this.methodName = methodName; 290 this.argClasses = argClasses; 291 } 292 293 public boolean equals(Object o2) { 294 if (this == o2) { 295 return true; 296 } 297 Signature that = (Signature)o2; 298 if (!(targetClass == that.targetClass)) { 299 return false; 300 } 301 if (!(methodName.equals(that.methodName))) { 302 return false; 303 } 304 if (argClasses.length != that.argClasses.length) { 305 return false; 306 } 307 for (int i = 0; i < argClasses.length; i++) { 308 if (!(argClasses[i] == that.argClasses[i])) { 309 return false; 310 } 311 } 312 return true; 313 } 314 315 319 public int hashCode() { 320 if (hashCode == 0) { 321 int result = 17; 322 result = 37 * result + targetClass.hashCode(); 323 result = 37 * result + methodName.hashCode(); 324 if (argClasses != null) { 325 for (int i = 0; i < argClasses.length; i++) { 326 result = 37 * result + ((argClasses[i] == null) ? 0 : 327 argClasses[i].hashCode()); 328 } 329 } 330 hashCode = result; 331 } 332 return hashCode; 333 } 334 } 335 336 341 public static synchronized Method getMethod(Class targetClass, 342 String methodName, 343 Class [] argClasses) { 344 Object signature = new Signature(targetClass, methodName, argClasses); 345 346 Method method = null; 347 Map methodCache = null; 348 boolean cache = false; 349 if (ReflectUtil.isPackageAccessible(targetClass)) { 350 cache = true; 351 } 352 353 if (cache && methodCacheRef != null && 354 (methodCache = (Map)methodCacheRef.get()) != null) { 355 method = (Method )methodCache.get(signature); 356 if (method != null) { 357 return method; 358 } 359 } 360 method = findMethod(targetClass, methodName, argClasses); 361 if (cache && method != null) { 362 if (methodCache == null) { 363 methodCache = new HashMap(); 364 methodCacheRef = new SoftReference (methodCache); 365 } 366 methodCache.put(signature, method); 367 } 368 return method; 369 } 370 371 376 public static Constructor getConstructor(Class cls, Class [] args) { 377 Constructor constructor = null; 378 379 Constructor [] ctors = ConstructorUtil.getConstructors(cls); 381 for(int i = 0; i < ctors.length; i++) { 382 if (matchArguments(args, ctors[i].getParameterTypes())) { 383 constructor = ctors[i]; 384 } 385 } 386 return constructor; 387 } 388 389 public static Object getPrivateField(Object instance, Class cls, String name) { 390 return getPrivateField(instance, cls, name); 391 } 392 393 402 public static Object getPrivateField(Object instance, Class cls, 403 String name, ExceptionListener el) { 404 try { 405 Field f = cls.getDeclaredField(name); 406 f.setAccessible(true); 407 return f.get(instance); 408 } 409 catch (Exception e) { 410 if (el != null) { 411 el.exceptionThrown(e); 412 } 413 } 414 return null; 415 } 416 } 417 | Popular Tags |