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 }