1 54 package org.logicalcobwebs.cglib.core; 55 56 import java.beans.*; 57 import java.lang.reflect.*; 58 import java.util.*; 59 import org.logicalcobwebs.asm.Type; 60 61 64 public class ReflectUtils { 65 private ReflectUtils() { } 66 67 private static final Map primitives = new HashMap(8); 68 private static final Map transforms = new HashMap(8); 69 private static final ClassLoader defaultLoader = ReflectUtils.class.getClassLoader(); 70 private static final RuntimePermission DEFINE_CGLIB_CLASS_IN_JAVA_PACKAGE_PERMISSION = 71 new RuntimePermission ("defineCGLIBClassInJavaPackage"); 72 private static final Method DEFINE_CLASS; 73 74 static { 75 try { 76 DEFINE_CLASS = ClassLoader .class.getDeclaredMethod("defineClass", new Class []{ byte[].class, int.class, int.class }); 77 } catch (NoSuchMethodException e) { 78 throw new CodeGenerationException(e); 79 } 80 } 81 82 private static final String [] CGLIB_PACKAGES = { 83 "java.lang", 84 }; 85 86 static { 87 primitives.put("byte", Byte.TYPE); 88 primitives.put("char", Character.TYPE); 89 primitives.put("double", Double.TYPE); 90 primitives.put("float", Float.TYPE); 91 primitives.put("int", Integer.TYPE); 92 primitives.put("long", Long.TYPE); 93 primitives.put("short", Short.TYPE); 94 primitives.put("boolean", Boolean.TYPE); 95 96 transforms.put("byte", "B"); 97 transforms.put("char", "C"); 98 transforms.put("double", "D"); 99 transforms.put("float", "F"); 100 transforms.put("int", "I"); 101 transforms.put("long", "J"); 102 transforms.put("short", "S"); 103 transforms.put("boolean", "Z"); 104 } 105 106 public static Type[] getExceptionTypes(Member member) { 107 if (member instanceof Method) { 108 return TypeUtils.getTypes(((Method)member).getExceptionTypes()); 109 } else if (member instanceof Constructor) { 110 return TypeUtils.getTypes(((Constructor)member).getExceptionTypes()); 111 } else { 112 throw new IllegalArgumentException ("Cannot get exception types of a field"); 113 } 114 } 115 116 public static Signature getSignature(Member member) { 117 if (member instanceof Method) { 118 return new Signature(member.getName(), Type.getMethodDescriptor((Method)member)); 119 } else if (member instanceof Constructor) { 120 Type[] types = TypeUtils.getTypes(((Constructor)member).getParameterTypes()); 121 return new Signature(Constants.CONSTRUCTOR_NAME, 122 Type.getMethodDescriptor(Type.VOID_TYPE, types)); 123 124 } else { 125 throw new IllegalArgumentException ("Cannot get signature of a field"); 126 } 127 } 128 129 public static Constructor findConstructor(String desc) { 130 return findConstructor(desc, defaultLoader); 131 } 132 133 public static Constructor findConstructor(String desc, ClassLoader loader) { 134 try { 135 int lparen = desc.indexOf('('); 136 String className = desc.substring(0, lparen).trim(); 137 return getClass(className, loader).getConstructor(parseTypes(desc, loader)); 138 } catch (ClassNotFoundException e) { 139 throw new CodeGenerationException(e); 140 } catch (NoSuchMethodException e) { 141 throw new CodeGenerationException(e); 142 } 143 } 144 145 public static Method findMethod(String desc) { 146 return findMethod(desc, defaultLoader); 147 } 148 149 public static Method findMethod(String desc, ClassLoader loader) { 150 try { 151 int lparen = desc.indexOf('('); 152 int dot = desc.lastIndexOf('.', lparen); 153 String className = desc.substring(0, dot).trim(); 154 String methodName = desc.substring(dot + 1, lparen).trim(); 155 return getClass(className, loader).getDeclaredMethod(methodName, parseTypes(desc, loader)); 156 } catch (ClassNotFoundException e) { 157 throw new CodeGenerationException(e); 158 } catch (NoSuchMethodException e) { 159 throw new CodeGenerationException(e); 160 } 161 } 162 163 private static Class [] parseTypes(String desc, ClassLoader loader) throws ClassNotFoundException { 164 int lparen = desc.indexOf('('); 165 int rparen = desc.indexOf(')', lparen); 166 List params = new ArrayList(); 167 int start = lparen + 1; 168 for (;;) { 169 int comma = desc.indexOf(',', start); 170 if (comma < 0) { 171 break; 172 } 173 params.add(desc.substring(start, comma).trim()); 174 start = comma + 1; 175 } 176 if (start < rparen) { 177 params.add(desc.substring(start, rparen).trim()); 178 } 179 Class [] types = new Class [params.size()]; 180 for (int i = 0; i < types.length; i++) { 181 types[i] = getClass((String )params.get(i), loader); 182 } 183 return types; 184 } 185 186 private static Class getClass(String className, ClassLoader loader) throws ClassNotFoundException { 187 return getClass(className, loader, CGLIB_PACKAGES); 188 } 189 190 private static Class getClass(String className, ClassLoader loader, String [] packages) throws ClassNotFoundException { 191 String save = className; 192 int dimensions = 0; 193 int index = 0; 194 while ((index = className.indexOf("[]", index) + 1) > 0) { 195 dimensions++; 196 } 197 StringBuffer brackets = new StringBuffer (className.length() - dimensions); 198 for (int i = 0; i < dimensions; i++) { 199 brackets.append('['); 200 } 201 className = className.substring(0, className.length() - 2 * dimensions); 202 203 String prefix = (dimensions > 0) ? brackets + "L" : ""; 204 String suffix = (dimensions > 0) ? ";" : ""; 205 try { 206 return Class.forName(prefix + className + suffix, false, loader); 207 } catch (ClassNotFoundException ignore) { } 208 for (int i = 0; i < packages.length; i++) { 209 try { 210 return Class.forName(prefix + packages[i] + '.' + className + suffix, false, loader); 211 } catch (ClassNotFoundException ignore) { } 212 } 213 if (dimensions == 0) { 214 Class c = (Class )primitives.get(className); 215 if (c != null) { 216 return c; 217 } 218 } else { 219 String transform = (String )transforms.get(className); 220 if (transform != null) { 221 try { 222 return Class.forName(brackets + transform, false, loader); 223 } catch (ClassNotFoundException ignore) { } 224 } 225 } 226 throw new ClassNotFoundException (save); 227 } 228 229 230 public static Object newInstance(Class type) { 231 return newInstance(type, Constants.EMPTY_CLASS_ARRAY, null); 232 } 233 234 public static Object newInstance(Class type, Class [] parameterTypes, Object [] args) { 235 return newInstance(getConstructor(type, parameterTypes), args); 236 } 237 238 public static Object newInstance(Constructor cstruct, Object [] args) { 239 boolean flag = cstruct.isAccessible(); 240 try { 241 cstruct.setAccessible(true); 242 Object result = cstruct.newInstance(args); 243 return result; 244 } catch (InstantiationException e) { 245 throw new CodeGenerationException(e); 246 } catch (IllegalAccessException e) { 247 throw new CodeGenerationException(e); 248 } catch (InvocationTargetException e) { 249 throw new CodeGenerationException(e.getTargetException()); 250 } finally { 251 cstruct.setAccessible(flag); 252 } 253 } 254 255 public static Constructor getConstructor(Class type, Class [] parameterTypes) { 256 try { 257 return type.getConstructor(parameterTypes); 258 } catch (NoSuchMethodException e) { 259 throw new CodeGenerationException(e); 260 } 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 public static Method findDeclaredMethod(Class type, String methodName, Class [] parameterTypes) 328 throws NoSuchMethodException { 329 Class cl = type; 330 while (cl != null) { 331 try { 332 return cl.getDeclaredMethod(methodName, parameterTypes); 333 } catch (NoSuchMethodException e) { 334 cl = cl.getSuperclass(); 335 } 336 } 337 throw new NoSuchMethodException (methodName); 338 } 339 340 public static List addAllMethods(Class type, List list) { 341 list.addAll(java.util.Arrays.asList(type.getDeclaredMethods())); 342 Class superclass = type.getSuperclass(); 343 if (superclass != null) { 344 addAllMethods(superclass, list); 345 } 346 Class [] interfaces = type.getInterfaces(); 347 for (int i = 0; i < interfaces.length; i++) { 348 addAllMethods(interfaces[i], list); 349 } 350 return list; 351 } 352 353 public static Method findInterfaceMethod(Class iface) { 354 if (!iface.isInterface()) { 355 throw new IllegalArgumentException (iface + " is not an interface"); 356 } 357 Method[] methods = iface.getDeclaredMethods(); 358 if (methods.length != 1) { 359 throw new IllegalArgumentException ("expecting exactly 1 method in " + iface); 360 } 361 return methods[0]; 362 } 363 364 public static Class defineClass(String className, byte[] b, ClassLoader loader) throws Exception { 365 SecurityManager sm = System.getSecurityManager(); 366 if (className != null && className.startsWith("java.") && sm != null) { 367 sm.checkPermission(DEFINE_CGLIB_CLASS_IN_JAVA_PACKAGE_PERMISSION); 368 } 369 Object [] args = new Object []{ b, new Integer (0), new Integer (b.length) }; 372 DEFINE_CLASS.setAccessible(true); 373 return (Class )DEFINE_CLASS.invoke(loader, args); 374 } 375 376 public static int findPackageProtected(Class [] classes) { 377 for (int i = 0; i < classes.length; i++) { 378 if (!Modifier.isPublic(classes[i].getModifiers())) { 379 return i; 380 } 381 } 382 return 0; 383 } 384 } 385 | Popular Tags |