1 16 package net.sf.cglib.core; 17 18 import java.beans.*; 19 import java.lang.reflect.*; 20 import java.security.AccessController ; 21 import java.security.PrivilegedAction ; 22 import java.security.ProtectionDomain ; 23 import java.util.*; 24 import org.objectweb.asm.Attribute; 25 import org.objectweb.asm.Type; 26 27 30 public class ReflectUtils { 31 private ReflectUtils() { } 32 33 private static final Map primitives = new HashMap(8); 34 private static final Map transforms = new HashMap(8); 35 private static final ClassLoader defaultLoader = ReflectUtils.class.getClassLoader(); 36 private static Method DEFINE_CLASS; 37 private static final ProtectionDomain PROTECTION_DOMAIN; 38 39 static { 40 PROTECTION_DOMAIN = (ProtectionDomain )AccessController.doPrivileged(new PrivilegedAction () { 41 public Object run() { 42 return ReflectUtils.class.getProtectionDomain(); 43 } 44 }); 45 46 AccessController.doPrivileged(new PrivilegedAction () { 47 public Object run() { 48 try { 49 Class loader = Class.forName("java.lang.ClassLoader"); DEFINE_CLASS = loader.getDeclaredMethod("defineClass", 51 new Class []{ String .class, 52 byte[].class, 53 Integer.TYPE, 54 Integer.TYPE, 55 ProtectionDomain .class }); 56 DEFINE_CLASS.setAccessible(true); 57 } catch (ClassNotFoundException e) { 58 throw new CodeGenerationException(e); 59 } catch (NoSuchMethodException e) { 60 throw new CodeGenerationException(e); 61 } 62 return null; 63 } 64 }); 65 } 66 67 private static final String [] CGLIB_PACKAGES = { 68 "java.lang", 69 }; 70 71 static { 72 primitives.put("byte", Byte.TYPE); 73 primitives.put("char", Character.TYPE); 74 primitives.put("double", Double.TYPE); 75 primitives.put("float", Float.TYPE); 76 primitives.put("int", Integer.TYPE); 77 primitives.put("long", Long.TYPE); 78 primitives.put("short", Short.TYPE); 79 primitives.put("boolean", Boolean.TYPE); 80 81 transforms.put("byte", "B"); 82 transforms.put("char", "C"); 83 transforms.put("double", "D"); 84 transforms.put("float", "F"); 85 transforms.put("int", "I"); 86 transforms.put("long", "J"); 87 transforms.put("short", "S"); 88 transforms.put("boolean", "Z"); 89 } 90 91 public static Type[] getExceptionTypes(Member member) { 92 if (member instanceof Method) { 93 return TypeUtils.getTypes(((Method)member).getExceptionTypes()); 94 } else if (member instanceof Constructor) { 95 return TypeUtils.getTypes(((Constructor)member).getExceptionTypes()); 96 } else { 97 throw new IllegalArgumentException ("Cannot get exception types of a field"); 98 } 99 } 100 101 public static Signature getSignature(Member member) { 102 if (member instanceof Method) { 103 return new Signature(member.getName(), Type.getMethodDescriptor((Method)member)); 104 } else if (member instanceof Constructor) { 105 Type[] types = TypeUtils.getTypes(((Constructor)member).getParameterTypes()); 106 return new Signature(Constants.CONSTRUCTOR_NAME, 107 Type.getMethodDescriptor(Type.VOID_TYPE, types)); 108 109 } else { 110 throw new IllegalArgumentException ("Cannot get signature of a field"); 111 } 112 } 113 114 public static Constructor findConstructor(String desc) { 115 return findConstructor(desc, defaultLoader); 116 } 117 118 public static Constructor findConstructor(String desc, ClassLoader loader) { 119 try { 120 int lparen = desc.indexOf('('); 121 String className = desc.substring(0, lparen).trim(); 122 return getClass(className, loader).getConstructor(parseTypes(desc, loader)); 123 } catch (ClassNotFoundException e) { 124 throw new CodeGenerationException(e); 125 } catch (NoSuchMethodException e) { 126 throw new CodeGenerationException(e); 127 } 128 } 129 130 public static Method findMethod(String desc) { 131 return findMethod(desc, defaultLoader); 132 } 133 134 public static Method findMethod(String desc, ClassLoader loader) { 135 try { 136 int lparen = desc.indexOf('('); 137 int dot = desc.lastIndexOf('.', lparen); 138 String className = desc.substring(0, dot).trim(); 139 String methodName = desc.substring(dot + 1, lparen).trim(); 140 return getClass(className, loader).getDeclaredMethod(methodName, parseTypes(desc, loader)); 141 } catch (ClassNotFoundException e) { 142 throw new CodeGenerationException(e); 143 } catch (NoSuchMethodException e) { 144 throw new CodeGenerationException(e); 145 } 146 } 147 148 private static Class [] parseTypes(String desc, ClassLoader loader) throws ClassNotFoundException { 149 int lparen = desc.indexOf('('); 150 int rparen = desc.indexOf(')', lparen); 151 List params = new ArrayList(); 152 int start = lparen + 1; 153 for (;;) { 154 int comma = desc.indexOf(',', start); 155 if (comma < 0) { 156 break; 157 } 158 params.add(desc.substring(start, comma).trim()); 159 start = comma + 1; 160 } 161 if (start < rparen) { 162 params.add(desc.substring(start, rparen).trim()); 163 } 164 Class [] types = new Class [params.size()]; 165 for (int i = 0; i < types.length; i++) { 166 types[i] = getClass((String )params.get(i), loader); 167 } 168 return types; 169 } 170 171 private static Class getClass(String className, ClassLoader loader) throws ClassNotFoundException { 172 return getClass(className, loader, CGLIB_PACKAGES); 173 } 174 175 private static Class getClass(String className, ClassLoader loader, String [] packages) throws ClassNotFoundException { 176 String save = className; 177 int dimensions = 0; 178 int index = 0; 179 while ((index = className.indexOf("[]", index) + 1) > 0) { 180 dimensions++; 181 } 182 StringBuffer brackets = new StringBuffer (className.length() - dimensions); 183 for (int i = 0; i < dimensions; i++) { 184 brackets.append('['); 185 } 186 className = className.substring(0, className.length() - 2 * dimensions); 187 188 String prefix = (dimensions > 0) ? brackets + "L" : ""; 189 String suffix = (dimensions > 0) ? ";" : ""; 190 try { 191 return Class.forName(prefix + className + suffix, false, loader); 192 } catch (ClassNotFoundException ignore) { } 193 for (int i = 0; i < packages.length; i++) { 194 try { 195 return Class.forName(prefix + packages[i] + '.' + className + suffix, false, loader); 196 } catch (ClassNotFoundException ignore) { } 197 } 198 if (dimensions == 0) { 199 Class c = (Class )primitives.get(className); 200 if (c != null) { 201 return c; 202 } 203 } else { 204 String transform = (String )transforms.get(className); 205 if (transform != null) { 206 try { 207 return Class.forName(brackets + transform, false, loader); 208 } catch (ClassNotFoundException ignore) { } 209 } 210 } 211 throw new ClassNotFoundException (save); 212 } 213 214 215 public static Object newInstance(Class type) { 216 return newInstance(type, Constants.EMPTY_CLASS_ARRAY, null); 217 } 218 219 public static Object newInstance(Class type, Class [] parameterTypes, Object [] args) { 220 return newInstance(getConstructor(type, parameterTypes), args); 221 } 222 223 public static Object newInstance(final Constructor cstruct, final Object [] args) { 224 225 boolean flag = cstruct.isAccessible(); 226 try { 227 cstruct.setAccessible(true); 228 Object result = cstruct.newInstance(args); 229 return result; 230 } catch (InstantiationException e) { 231 throw new CodeGenerationException(e); 232 } catch (IllegalAccessException e) { 233 throw new CodeGenerationException(e); 234 } catch (InvocationTargetException e) { 235 throw new CodeGenerationException(e.getTargetException()); 236 } finally { 237 cstruct.setAccessible(flag); 238 } 239 240 } 241 242 public static Constructor getConstructor(Class type, Class [] parameterTypes) { 243 try { 244 Constructor constructor = type.getDeclaredConstructor(parameterTypes); 245 constructor.setAccessible(true); 246 return constructor; 247 } catch (NoSuchMethodException e) { 248 throw new CodeGenerationException(e); 249 } 250 } 251 252 public static String [] getNames(Class [] classes) 253 { 254 if (classes == null) 255 return null; 256 String [] names = new String [classes.length]; 257 for (int i = 0; i < names.length; i++) { 258 names[i] = classes[i].getName(); 259 } 260 return names; 261 } 262 263 public static Class [] getClasses(Object [] objects) { 264 Class [] classes = new Class [objects.length]; 265 for (int i = 0; i < objects.length; i++) { 266 classes[i] = objects[i].getClass(); 267 } 268 return classes; 269 } 270 271 public static Method findNewInstance(Class iface) { 272 Method m = findInterfaceMethod(iface); 273 if (!m.getName().equals("newInstance")) { 274 throw new IllegalArgumentException (iface + " missing newInstance method"); 275 } 276 return m; 277 } 278 279 public static Method[] getPropertyMethods(PropertyDescriptor[] properties, boolean read, boolean write) { 280 Set methods = new HashSet(); 281 for (int i = 0; i < properties.length; i++) { 282 PropertyDescriptor pd = properties[i]; 283 if (read) { 284 methods.add(pd.getReadMethod()); 285 } 286 if (write) { 287 methods.add(pd.getWriteMethod()); 288 } 289 } 290 methods.remove(null); 291 return (Method[])methods.toArray(new Method[methods.size()]); 292 } 293 294 public static PropertyDescriptor[] getBeanProperties(Class type) { 295 return getPropertiesHelper(type, true, true); 296 } 297 298 public static PropertyDescriptor[] getBeanGetters(Class type) { 299 return getPropertiesHelper(type, true, false); 300 } 301 302 public static PropertyDescriptor[] getBeanSetters(Class type) { 303 return getPropertiesHelper(type, false, true); 304 } 305 306 private static PropertyDescriptor[] getPropertiesHelper(Class type, boolean read, boolean write) { 307 try { 308 BeanInfo info = Introspector.getBeanInfo(type, Object .class); 309 PropertyDescriptor[] all = info.getPropertyDescriptors(); 310 if (read && write) { 311 return all; 312 } 313 List properties = new ArrayList(all.length); 314 for (int i = 0; i < all.length; i++) { 315 PropertyDescriptor pd = all[i]; 316 if ((read && pd.getReadMethod() != null) || 317 (write && pd.getWriteMethod() != null)) { 318 properties.add(pd); 319 } 320 } 321 return (PropertyDescriptor[])properties.toArray(new PropertyDescriptor[properties.size()]); 322 } catch (IntrospectionException e) { 323 throw new CodeGenerationException(e); 324 } 325 } 326 327 328 329 public static Method findDeclaredMethod(final Class type, 330 final String methodName, final Class [] parameterTypes) 331 throws NoSuchMethodException { 332 333 Class cl = type; 334 while (cl != null) { 335 try { 336 return cl.getDeclaredMethod(methodName, parameterTypes); 337 } catch (NoSuchMethodException e) { 338 cl = cl.getSuperclass(); 339 } 340 } 341 throw new NoSuchMethodException (methodName); 342 343 } 344 345 public static List addAllMethods(final Class type, final List list) { 346 347 348 list.addAll(java.util.Arrays.asList(type.getDeclaredMethods())); 349 Class superclass = type.getSuperclass(); 350 if (superclass != null) { 351 addAllMethods(superclass, list); 352 } 353 Class [] interfaces = type.getInterfaces(); 354 for (int i = 0; i < interfaces.length; i++) { 355 addAllMethods(interfaces[i], list); 356 } 357 358 return list; 359 } 360 361 public static List addAllInterfaces(Class type, List list) { 362 Class superclass = type.getSuperclass(); 363 if (superclass != null) { 364 list.addAll(Arrays.asList(type.getInterfaces())); 365 addAllInterfaces(superclass, list); 366 } 367 return list; 368 } 369 370 371 public static Method findInterfaceMethod(Class iface) { 372 if (!iface.isInterface()) { 373 throw new IllegalArgumentException (iface + " is not an interface"); 374 } 375 Method[] methods = iface.getDeclaredMethods(); 376 if (methods.length != 1) { 377 throw new IllegalArgumentException ("expecting exactly 1 method in " + iface); 378 } 379 return methods[0]; 380 } 381 382 public static Class defineClass(String className, byte[] b, ClassLoader loader) throws Exception { 383 Object [] args = new Object []{className, b, new Integer (0), new Integer (b.length), PROTECTION_DOMAIN }; 384 return (Class )DEFINE_CLASS.invoke(loader, args); 385 } 386 387 public static int findPackageProtected(Class [] classes) { 388 for (int i = 0; i < classes.length; i++) { 389 if (!Modifier.isPublic(classes[i].getModifiers())) { 390 return i; 391 } 392 } 393 return 0; 394 } 395 396 public static MethodInfo getMethodInfo(final Member member, final int modifiers) { 397 final Signature sig = getSignature(member); 398 return new MethodInfo() { 399 private ClassInfo ci; 400 public ClassInfo getClassInfo() { 401 if (ci == null) 402 ci = ReflectUtils.getClassInfo(member.getDeclaringClass()); 403 return ci; 404 } 405 public int getModifiers() { 406 return modifiers; 407 } 408 public Signature getSignature() { 409 return sig; 410 } 411 public Type[] getExceptionTypes() { 412 return ReflectUtils.getExceptionTypes(member); 413 } 414 public Attribute getAttribute() { 415 return null; 416 } 417 }; 418 } 419 420 public static MethodInfo getMethodInfo(Member member) { 421 return getMethodInfo(member, member.getModifiers()); 422 } 423 424 public static ClassInfo getClassInfo(final Class clazz) { 425 final Type type = Type.getType(clazz); 426 final Type sc = (clazz.getSuperclass() == null) ? null : Type.getType(clazz.getSuperclass()); 427 return new ClassInfo() { 428 public Type getType() { 429 return type; 430 } 431 public Type getSuperType() { 432 return sc; 433 } 434 public Type[] getInterfaces() { 435 return TypeUtils.getTypes(clazz.getInterfaces()); 436 } 437 public int getModifiers() { 438 return clazz.getModifiers(); 439 } 440 }; 441 } 442 443 public static Method[] findMethods(String [] namesAndDescriptors, Method[] methods) 445 { 446 Map map = new HashMap(); 447 for (int i = 0; i < methods.length; i++) { 448 Method method = methods[i]; 449 map.put(method.getName() + Type.getMethodDescriptor(method), method); 450 } 451 Method[] result = new Method[namesAndDescriptors.length / 2]; 452 for (int i = 0; i < result.length; i++) { 453 result[i] = (Method)map.get(namesAndDescriptors[i * 2] + namesAndDescriptors[i * 2 + 1]); 454 if (result[i] == null) { 455 } 457 } 458 return result; 459 } 460 } 461 | Popular Tags |