KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > inversoft > util > ReflectionTools


1 /*
2  * Copyright (c) 2003, Inversoft
3  *
4  * This software is distribuable under the GNU Lesser General Public License.
5  * For more information visit gnu.org.
6  */

7 package com.inversoft.util;
8
9
10 import java.lang.reflect.InvocationTargetException JavaDoc;
11 import java.lang.reflect.Method JavaDoc;
12
13
14 /**
15  * This class is a toolkit to help in reflection. All
16  * JavaBean related methods and toolkit methods can be found
17  * in the com.bp.beans package
18  *
19  * @author Brian Pontarelli
20  */

21 public class ReflectionTools {
22
23     /**
24      * Convience method that returns class given the class name
25      *
26      * @param className The name of the class (ie Foo)
27      * @return The Class object for the class if it is found
28      * @throws ReflectionException If the class name is invalid
29      */

30     public static Class JavaDoc findClass(String JavaDoc className) throws ReflectionException {
31         return findClass(className, null);
32     }
33
34     /**
35      * Convience method that returns class given the package name and className
36      *
37      * @param className The name of the class (ie Foo)
38      * @param packageName (Optional) The name of the package (ie com.xor.util)
39      * @return The Class object for the class if it is found
40      * @throws ReflectionException If the class name is invalid
41      */

42     public static Class JavaDoc findClass(String JavaDoc className, String JavaDoc packageName)
43     throws ReflectionException {
44
45         assert (className != null) : "className == null";
46
47         Class JavaDoc klass = null;
48         try {
49             if (StringTools.isTrimmedEmpty(packageName)) {
50                 klass = Class.forName(className);
51             } else {
52                 klass = Class.forName(packageName + "." + className);
53             }
54         } catch (ClassNotFoundException JavaDoc cnfe) {
55             throw new ReflectionException("Class not found: " + cnfe.getMessage(),
56                 cnfe);
57         }
58
59         return klass;
60     }
61
62     /**
63      * Returns the given class' method with the name method and the parameters
64      * params. This is really just a convience method so that code doesn't have
65      * to catch all five thousand exceptions that Java reflection throws and
66      * make nifty error messages, this does all of that for you and throws a
67      * single, simple exception instead
68      *
69      * @param klass The class object to get the method from
70      * @param method The name of the method to fetch
71      * @param params The params to the method (can be null if the method does
72      * not take any parameters)
73      * @return The Method
74      * @throws ReflectionException If anything went wrong in the reflection,
75      * like wrong arguments to the method or invalid method name. This
76      * exception has a very good message body that tells exactly what
77      * the hell you screwed up
78      */

79     public static Method JavaDoc getMethod(Class JavaDoc klass, String JavaDoc method, Class JavaDoc [] params)
80     throws ReflectionException {
81         try {
82             return klass.getMethod(method, params);
83         } catch (NoSuchMethodException JavaDoc nsme) {
84             throw new ReflectionException("No such method: " + nsme.getMessage(),
85                 nsme);
86         } catch (SecurityException JavaDoc se) {
87             StringBuffer JavaDoc error = new StringBuffer JavaDoc();
88             error.append("Security violation accessing method ");
89             error.append(klass.getName());
90             error.append("#");
91             error.append(method);
92             error.append("(");
93             for (int i = 0; params != null && i < params.length; i++) {
94                 error.append(params[i].getName());
95             }
96             error.append(")");
97             throw new ReflectionException(error.toString(), se);
98         }
99     }
100
101     /**
102      * Gets all the methods for the given class and handles all the nasty exceptions
103      * that Java reflection can throw. This throws a nice exception.
104      *
105      * @param klass The class to get the methods from (only the public ones)
106      * @return The methods
107      * @throws ReflectionException If anything bad happened during reflection
108      */

109     public static Method JavaDoc [] getMethods(Class JavaDoc klass) throws ReflectionException {
110         try {
111             return klass.getMethods();
112         } catch (SecurityException JavaDoc se) {
113             StringBuffer JavaDoc error = new StringBuffer JavaDoc();
114             error.append("Security violation getting methods of class: ");
115             error.append(klass.getName());
116             throw new ReflectionException(error.toString(), se);
117         }
118     }
119
120     /**
121      * Using the Class, method name and parameters, this method attempts to locate
122      * a method in the given Class. If this method is not found, this method
123      * uses the Class object in the params array at the indices given and mutates
124      * the params array to contain the super-class or super-interface. What this
125      * does is allows methods that declare a specific Class or any of its parents
126      * to be located.
127      * </p>
128      *
129      * <p>
130      * An example of this would be a Class named Parent who has one child class
131      * named Child. This method would resolve this method if it exists in the
132      * Class:
133      * </p>
134      * <code>public void doSomething(Child child)</code>
135      * <p>
136      * Or this method if the above method does not exist
137      * </p>
138      * <code>public void doSomething(Parent parent)</code>
139      * <p>
140      * The resolution can also handle this case as long as indices is 1:
141      * </p>
142      * <code>public void doSomething(String name, Parent parent)</code>
143      * <code>public void doSomething(String name, Child child)</code>
144      *
145      * <strong>This does nto currently work with interfaces</strong>
146      *
147      * @param klass The class object to get the method from
148      * @param method The name of the method to fetch
149      * @param params The params to the method (can be null if the method does
150      * not take any parameters)
151      * @param index This is the indices within the params array that is used to
152      * search for the method using super-classes or super-interfaces.
153      * @return The Method or null if it could not be found
154      */

155     public static Method JavaDoc findMethod(Class JavaDoc klass, String JavaDoc method, Class JavaDoc [] params,
156             int index) {
157         Class JavaDoc [] localParams = new Class JavaDoc[params.length];
158         System.arraycopy(params, 0, localParams, 0, params.length);
159
160         Class JavaDoc type = localParams[index];
161         Method JavaDoc methodObj = null;
162         while (type != null) {
163             localParams[index] = type;
164
165             try {
166                 methodObj = klass.getMethod(method, localParams);
167                 break;
168             } catch (NoSuchMethodException JavaDoc nsme) {
169                 // Smother and move to the next method attempt
170
type = localParams[index].getSuperclass();
171             } catch (SecurityException JavaDoc se) {
172                 // Smother and move to the next method attempt
173
type = localParams[index].getSuperclass();
174             }
175         }
176
177         return methodObj;
178     }
179
180     /**
181      * Another convience method because invoking a reflected method is a really
182      * pain in the butt. It can throw like five billion exceptions and really
183      * make coding a lame experience. So, I've wrapped all those exceptions up
184      * and thrown a nice exception of my own making called ReflectionException.
185      * Although, for debugging purposes, this method will re-throw invocation
186      * target exceptions of type Error and RuntimeException. For example,
187      * NullPointerExceptions and OutOfMemoryError are not wrapped in a
188      * ReflectionException. Instead they are re-thrown. All other invocation
189      * target exceptions are unwrapped from the InvocationTargetException class
190      * and re-wrapped into a new ReflectionException as the target property.
191      *
192      * @param method The method to invoke
193      * @param object The object to invoke the method on
194      * @param params The params to the method
195      * @return The return value from the method
196      * @throws ReflectionException If any mishap occurred whilst Reflecting sire.
197      * All the exceptions that could be thrown whilst invoking will be
198      * wrapped inside the ReflectionException
199      * @throws RuntimeException If the target of the InvocationTargetException is
200      * a RuntimeException, in which case, it is re-thrown
201      * @throws Error If the target of the InvocationTargetException is an Error,
202      * in which case, it is re-thrown
203      */

204     public static Object JavaDoc invokeMethod(Method JavaDoc method, Object JavaDoc object, Object JavaDoc [] params)
205     throws ReflectionException, RuntimeException JavaDoc, Error JavaDoc {
206         try {
207             return method.invoke(object, params);
208         } catch (IllegalAccessException JavaDoc iae) {
209             StringBuffer JavaDoc error = new StringBuffer JavaDoc();
210             error.append("Access error for method: ");
211             error.append(method.toString());
212             throw new ReflectionException(error.toString(), iae);
213         } catch (IllegalArgumentException JavaDoc iare) {
214             StringBuffer JavaDoc error = new StringBuffer JavaDoc();
215             error.append("Error while calling method: ").append(method.toString());
216             throw new ReflectionException(error.toString(), iare);
217         } catch (InvocationTargetException JavaDoc ite) {
218
219             // Check if the target is a runtime or error and re-throw it
220
Throwable JavaDoc target = ite.getTargetException();
221
222             if (target instanceof RuntimeException JavaDoc) {
223                 throw (RuntimeException JavaDoc) target;
224             }
225
226             if (target instanceof Error JavaDoc) {
227                 throw (Error JavaDoc) target;
228             }
229
230             StringBuffer JavaDoc error = new StringBuffer JavaDoc();
231             error.append("Method ");
232             error.append(method.toString());
233             error.append(" threw exception: ");
234             error.append(target.toString());
235             throw new ReflectionException(error.toString(), ite, target);
236         }
237     }
238
239     /**
240      * Yep, another convience method that instantiates an object from a class
241      * and this is just like all the others and wraps the exceptions into one
242      * nice exception.
243      *
244      * @param objectClass The class to instantiate
245      * @return The new instance of the class
246      * @throws ReflectionException If you did something really dumb like put
247      * a security restriction on the class or tried to call a class
248      * that doesn't have a default constructor of something lame like
249      * that.
250      */

251     public static Object JavaDoc instantiate(Class JavaDoc objectClass) throws ReflectionException {
252         try {
253             return objectClass.newInstance();
254         } catch (InstantiationException JavaDoc ie) {
255             throw new ReflectionException("Error instantiating " +
256                 objectClass.getName(), ie);
257         } catch (IllegalAccessException JavaDoc iae) {
258             throw new ReflectionException("Access violation instantiating " +
259                 objectClass.getName(), iae);
260         } catch (SecurityException JavaDoc se) {
261             throw new ReflectionException("Security violation instantiating " +
262                 objectClass.getName(), se);
263         }
264     }
265
266     /**
267      * A convience method so that a class can be instantiated by name stored in
268      * a string without all the exceptions having to be caught. Instead a single
269      * ReflectionException is caught and contains a descriptive message about the
270      * error.
271      *
272      * @param className The name of the class to instantiate
273      * @return The new instance of the class
274      * @throws ReflectionException if something went wrong during name lookup
275      * or instantiation
276      */

277     public static Object JavaDoc instantiate(String JavaDoc className) throws ReflectionException {
278         try {
279             return instantiate(Class.forName(className));
280         } catch (ClassNotFoundException JavaDoc cnfe) {
281             throw new ReflectionException("Class " + className +
282                 " not found in class path", cnfe);
283         }
284     }
285
286     /**
287      * Converts the type given to the correct wrapper class for that type. If
288      * the type given is not a primitive type then null is returned. If the type
289      * given is a wrapper class, then null is returned.
290      *
291      * @param type The type of convert to its wrapper class
292      * @return The wrapper type for the type given or null
293     */

294     public static Class JavaDoc convertToWrapper(Class JavaDoc type) {
295
296         if (!type.isPrimitive()) {
297             return null;
298         }
299
300         Class JavaDoc klass = null;
301         if (type == Boolean.TYPE) {
302             klass = Boolean JavaDoc.class;
303         } else if (type == Byte.TYPE) {
304             klass = Byte JavaDoc.class;
305         } else if (type == Character.TYPE) {
306             klass = Character JavaDoc.class;
307         } else if (type == Short.TYPE) {
308             klass = Short JavaDoc.class;
309         } else if (type == Integer.TYPE) {
310             klass = Integer JavaDoc.class;
311         } else if (type == Long.TYPE) {
312             klass = Long JavaDoc.class;
313         } else if (type == Float.TYPE) {
314             klass = Float JavaDoc.class;
315         } else if (type == Double.TYPE) {
316             klass = Double JavaDoc.class;
317         }
318
319         return klass;
320     }
321 }
322
Popular Tags