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 */
022 package org.granite.util;
023
024 import java.lang.annotation.Annotation;
025 import java.lang.reflect.Field;
026 import java.lang.reflect.InvocationTargetException;
027 import java.lang.reflect.Method;
028 import java.lang.reflect.ParameterizedType;
029 import java.lang.reflect.Type;
030 import java.util.ArrayList;
031 import 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 */
040 public 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 }