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