001    package org.granite.util;
002    
003    import java.lang.annotation.Annotation;
004    import java.lang.reflect.Field;
005    import java.lang.reflect.InvocationTargetException;
006    import java.lang.reflect.Method;
007    import java.lang.reflect.ParameterizedType;
008    import java.lang.reflect.Type;
009    import java.util.ArrayList;
010    import 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     */
019    public 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    }