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