001package org.granite.util; 002 003import java.lang.annotation.Annotation; 004import java.lang.reflect.Field; 005import java.lang.reflect.InvocationTargetException; 006import java.lang.reflect.Method; 007import java.lang.reflect.ParameterizedType; 008import java.lang.reflect.Type; 009import java.util.ArrayList; 010import java.util.List; 011 012/** 013 * Reflections class copied from JBoss Seam. 014 * www.seamframework.org 015 * jboss-seam-2.0.0.GA 016 * Author unattributed 017 * 018 */ 019public class Reflections 020{ 021 022 public static Object invoke(Method method, Object target, Object... args) throws Exception 023 { 024 try 025 { 026 return method.invoke( target, args ); 027 } 028 catch (IllegalArgumentException iae) 029 { 030 String message = "Could not invoke method by reflection: " + toString(method); 031 if (args!=null && args.length>0) 032 { 033 message += " with parameters: (" + Strings.toClassNameString(", ", args) + ')'; 034 } 035 message += " on: " + target.getClass().getName(); 036 throw new IllegalArgumentException(message, iae); 037 } 038 catch (InvocationTargetException ite) 039 { 040 if ( ite.getCause() instanceof Exception ) 041 { 042 throw (Exception) ite.getCause(); 043 } 044 045 throw ite; 046 } 047 } 048 049 public static Object get(Field field, Object target) throws Exception 050 { 051 try 052 { 053 return field.get(target); 054 } 055 catch (IllegalArgumentException iae) 056 { 057 String message = "Could not get field value by reflection: " + toString(field) + 058 " on: " + target.getClass().getName(); 059 throw new IllegalArgumentException(message, iae); 060 } 061 } 062 063 public static void set(Field field, Object target, Object value) throws Exception 064 { 065 try 066 { 067 field.set(target, value); 068 } 069 catch (IllegalArgumentException iae) 070 { 071 // target may be null if field is static so use field.getDeclaringClass() instead 072 String message = "Could not set field value by reflection: " + toString(field) + 073 " on: " + field.getDeclaringClass().getName(); 074 if (value==null) 075 { 076 message += " with null value"; 077 } 078 else 079 { 080 message += " with value: " + value.getClass(); 081 } 082 throw new IllegalArgumentException(message, iae); 083 } 084 } 085 086 public static Object getAndWrap(Field field, Object target) 087 { 088 try 089 { 090 return get(field, target); 091 } 092 catch (Exception e) 093 { 094 if (e instanceof RuntimeException) 095 { 096 throw (RuntimeException) e; 097 } 098 099 throw new IllegalArgumentException("exception setting: " + field.getName(), e); 100 } 101 } 102 103 public static void setAndWrap(Field field, Object target, Object value) 104 { 105 try 106 { 107 set(field, target, value); 108 } 109 catch (Exception e) 110 { 111 if (e instanceof RuntimeException) 112 { 113 throw (RuntimeException) e; 114 } 115 116 throw new IllegalArgumentException("exception setting: " + field.getName(), e); 117 } 118 } 119 120 public static Object invokeAndWrap(Method method, Object target, Object... args) 121 { 122 try 123 { 124 return invoke(method, target, args); 125 } 126 catch (Exception e) 127 { 128 if (e instanceof RuntimeException) 129 { 130 throw (RuntimeException) e; 131 } 132 133 throw new RuntimeException("exception invoking: " + method.getName(), e); 134 } 135 } 136 137 private static String toString(Method method) 138 { 139 return Strings.unqualify( method.getDeclaringClass().getName() ) + 140 '.' + 141 method.getName() + 142 '(' + 143 Strings.toString( ", ", method.getParameterTypes() ) + 144 ')'; 145 } 146 147 private static String toString(Field field) 148 { 149 return Strings.unqualify( field.getDeclaringClass().getName() ) + 150 '.' + 151 field.getName(); 152 } 153 154 public static Class<?> classForName(String name) throws ClassNotFoundException 155 { 156 try 157 { 158 return Thread.currentThread().getContextClassLoader().loadClass(name); 159 } 160 catch (Exception e) 161 { 162 return Class.forName(name); 163 } 164 } 165 166 /** 167 * Return's true if the class can be loaded using Reflections.classForName() 168 */ 169 public static boolean isClassAvailable(String name) 170 { 171 try 172 { 173 classForName(name); 174 } 175 catch (ClassNotFoundException e) { 176 return false; 177 } 178 return true; 179 } 180 181 public static Class<?> getCollectionElementType(Type collectionType) 182 { 183 if ( !(collectionType instanceof ParameterizedType) ) 184 { 185 throw new IllegalArgumentException("collection type not parameterized"); 186 } 187 Type[] typeArguments = ( (ParameterizedType) collectionType ).getActualTypeArguments(); 188 if (typeArguments.length==0) 189 { 190 throw new IllegalArgumentException("no type arguments for collection type"); 191 } 192 Type typeArgument = typeArguments.length==1 ? typeArguments[0] : typeArguments[1]; //handle Maps 193 if ( !(typeArgument instanceof Class<?>) ) 194 { 195 throw new IllegalArgumentException("type argument not a class"); 196 } 197 return (Class<?>) typeArgument; 198 } 199 200 public static Class<?> getMapKeyType(Type collectionType) 201 { 202 if ( !(collectionType instanceof ParameterizedType) ) 203 { 204 throw new IllegalArgumentException("collection type not parameterized"); 205 } 206 Type[] typeArguments = ( (ParameterizedType) collectionType ).getActualTypeArguments(); 207 if (typeArguments.length==0) 208 { 209 throw new IllegalArgumentException("no type arguments for collection type"); 210 } 211 Type typeArgument = typeArguments[0]; 212 if ( !(typeArgument instanceof Class<?>) ) 213 { 214 throw new IllegalArgumentException("type argument not a class"); 215 } 216 return (Class<?>) typeArgument; 217 } 218 219 public static Method getSetterMethod(Class<?> clazz, String name) 220 { 221 Method[] methods = clazz.getMethods(); 222 for (Method method: methods) 223 { 224 String methodName = method.getName(); 225 if ( methodName.startsWith("set") && method.getParameterTypes().length==1 ) 226 { 227 if ( Introspector.decapitalize( methodName.substring(3) ).equals(name) ) 228 { 229 return method; 230 } 231 } 232 } 233 throw new IllegalArgumentException("no such setter method: " + clazz.getName() + '.' + name); 234 } 235 236 public static Method getGetterMethod(Class<?> clazz, String name) { 237 Method[] methods = clazz.getMethods(); 238 for (Method method : methods) { 239 String methodName = method.getName(); 240 if (methodName.matches("^(get|is).*") && method.getParameterTypes().length == 0) { 241 int idx = methodName.startsWith("get") ? 3 : 2; 242 if (Introspector.decapitalize(methodName.substring(idx)).equals(name)) 243 return method; 244 } 245 } 246 throw new IllegalArgumentException("no such getter method: " + clazz.getName() + '.' + name); 247 } 248 249 /** 250 * Get all the getter methods annotated with the given annotation. Returns an empty list if 251 * none are found 252 */ 253 public static List<Method> getGetterMethods(Class<?> clazz, Class<? extends Annotation> annotation) 254 { 255 List<Method> methods = new ArrayList<Method>(); 256 for (Method method : clazz.getMethods()) 257 { 258 if (method.isAnnotationPresent(annotation)) 259 { 260 methods.add(method); 261 } 262 } 263 return methods; 264 } 265 266 public static Field getField(Class<?> clazz, String name) 267 { 268 for ( Class<?> superClass = clazz; superClass!=Object.class; superClass=superClass.getSuperclass() ) 269 { 270 try 271 { 272 return superClass.getDeclaredField(name); 273 } 274 catch (NoSuchFieldException nsfe) {} 275 } 276 throw new IllegalArgumentException("no such field: " + clazz.getName() + '.' + name); 277 } 278 279 /** 280 * Get all the fields which are annotated with the given annotation. Returns an empty list 281 * if none are found 282 */ 283 public static List<Field> getFields(Class<?> clazz, Class<? extends Annotation> annotation) 284 { 285 List<Field> fields = new ArrayList<Field>(); 286 for (Class<?> superClass = clazz; superClass!=Object.class; superClass=superClass.getSuperclass()) 287 { 288 for (Field field : superClass.getDeclaredFields()) 289 { 290 if (field.isAnnotationPresent(annotation)) 291 { 292 fields.add(field); 293 } 294 } 295 } 296 return fields; 297 } 298 299 public static Method getMethod(Annotation annotation, String name) 300 { 301 try 302 { 303 return annotation.annotationType().getMethod(name); 304 } 305 catch (NoSuchMethodException nsme) 306 { 307 return null; 308 } 309 } 310 311 public static boolean isInstanceOf(Class<?> clazz, String name) 312 { 313 if (name == null) 314 { 315 throw new IllegalArgumentException("name cannot be null"); 316 } 317 for (Class<?> c = clazz; c != Object.class; c = c.getSuperclass()) 318 { 319 if (name.equals(c.getName())) 320 { 321 return true; 322 } 323 } 324 for (Class<?> c : clazz.getInterfaces()) 325 { 326 if (name.equals(c.getName())) 327 { 328 return true; 329 } 330 } 331 return false; 332 } 333 334 335 public static Object get(Object object, String fieldName) { 336 Field field = null; 337 for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) { 338 try { 339 field = superClass.getDeclaredField(fieldName); 340 break; 341 } 342 catch (NoSuchFieldException nsfe) { 343 } 344 } 345 if (field == null) 346 throw new RuntimeException("Could not find field " + fieldName + " of " + object); 347 field.setAccessible(true); 348 try { 349 return field.get(object); 350 } 351 catch (Exception e) { 352 throw new RuntimeException("Could not get field " + fieldName + " of " + object, e); 353 } 354 } 355 356 @SuppressWarnings("unchecked") 357 public static <T> T get(Object object, String fieldName, Class<T> valueClass) { 358 Field field = null; 359 for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) { 360 try { 361 field = superClass.getDeclaredField(fieldName); 362 break; 363 } 364 catch (NoSuchFieldException nsfe) { 365 } 366 } 367 if (field == null) 368 throw new RuntimeException("Could not find field " + fieldName + " of " + object); 369 field.setAccessible(true); 370 try { 371 return (T)field.get(object); 372 } 373 catch (Exception e) { 374 throw new RuntimeException("Could not get field " + fieldName + " of " + object, e); 375 } 376 } 377}