001: /*--
002:
003: Copyright (C) 2001 Anthony Eden.
004: All rights reserved.
005:
006: Redistribution and use in source and binary forms, with or without
007: modification, are permitted provided that the following conditions
008: are met:
009:
010: 1. Redistributions of source code must retain the above copyright
011: notice, this list of conditions, and the following disclaimer.
012:
013: 2. Redistributions in binary form must reproduce the above copyright
014: notice, this list of conditions, and the disclaimer that follows
015: these conditions in the documentation and/or other materials
016: provided with the distribution.
017:
018: 3. The name "EdenLib" must not be used to endorse or promote products
019: derived from this software without prior written permission. For
020: written permission, please contact me@anthonyeden.com.
021:
022: 4. Products derived from this software may not be called "EdenLib", nor
023: may "EdenLib" appear in their name, without prior written permission
024: from Anthony Eden (me@anthonyeden.com).
025:
026: In addition, I request (but do not require) that you include in the
027: end-user documentation provided with the redistribution and/or in the
028: software itself an acknowledgement equivalent to the following:
029: "This product includes software developed by
030: Anthony Eden (http://www.anthonyeden.com/)."
031:
032: THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
033: WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
034: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
035: DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
036: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
037: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
038: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
039: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
040: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
041: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
042: POSSIBILITY OF SUCH DAMAGE.
043:
044: For more information on EdenLib, please see <http://edenlib.sf.net/>.
045:
046: */
047:
048: package com.anthonyeden.lib.util;
049:
050: import java.lang.reflect.Method;
051: import java.lang.reflect.InvocationTargetException;
052:
053: /** Utilities for invoking methods at runtime using reflection.
054:
055: @author Anthony Eden
056: */
057:
058: public class MethodUtilities {
059:
060: private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
061: private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
062:
063: private MethodUtilities() {
064:
065: }
066:
067: /** Invoke the given method. This method is a convenience method which
068: creates an array of arguments with the single arg value. This is
069: necessary because the Method.invoke() method only accepts an array of
070: argument objects.
071:
072: @param method The method
073: @param target The target Object
074: @param arg A single argument
075: @return The return object or null
076: @throws IllegalAccessException
077: @throws IllegalArgumentException
078: @throws InvocationTargetException
079: */
080:
081: public static Object invoke(Method method, Object target, Object arg)
082: throws IllegalAccessException, IllegalArgumentException,
083: InvocationTargetException {
084: if (arg == null) {
085: return invoke(method, target, EMPTY_OBJECT_ARRAY);
086: } else {
087: Object[] args = new Object[1];
088: args[0] = arg;
089: return invoke(method, target, args);
090: }
091: }
092:
093: /** Invoke the given method. This method actually invokes the target
094: method with the given arguments.
095:
096: @param method The Method
097: @param target The target Object
098: @param args An array of argument Objects
099: @return The return value
100: @throws IllegalAccessException
101: @throws IllegalArgumentException
102: @throws InvocationTargetException
103: */
104:
105: public static Object invoke(Method method, Object target,
106: Object[] args) throws IllegalAccessException,
107: IllegalArgumentException, InvocationTargetException {
108: return method.invoke(target, args);
109: }
110:
111: /** Invoke the given method. The target object is used to determine
112: the target class and which is then used to get a Method object.
113: This method is a convenience method which creates an array of arguments
114: with the single arg value. This is necessary because the
115: Method.invoke() method only accepts an array of argument objects.
116:
117: @param methodName The method name
118: @param target The target Object
119: @param arg A single argument
120: @return The return object or null
121: @throws IllegalAccessException
122: @throws IllegalArgumentException
123: @throws InvocationTargetException
124: @throws NoSuchMethodException
125: @throws SecurityException
126: */
127:
128: public static Object invoke(String methodName, Object target,
129: Object arg) throws IllegalAccessException,
130: IllegalArgumentException, InvocationTargetException,
131: NoSuchMethodException, SecurityException {
132: if (arg == null) {
133: return invoke(methodName, target, EMPTY_OBJECT_ARRAY);
134: } else {
135: Object[] args = new Object[1];
136: args[0] = arg;
137: return invoke(methodName, target, args);
138: }
139: }
140:
141: /** Invoke the given method. The target object is used to determine
142: the target class and which is then used to get a Method object.
143:
144: @param methodName The Method name
145: @param target The target Object
146: @param args An array of argument Objects
147: @return The return value
148: @throws IllegalAccessException
149: @throws IllegalArgumentException
150: @throws InvocationTargetException
151: @throws NoSuchMethodException
152: @throws SecurityException
153: */
154:
155: public static Object invoke(String methodName, Object target,
156: Object[] args) throws IllegalAccessException,
157: IllegalArgumentException, InvocationTargetException,
158: NoSuchMethodException, SecurityException {
159: return invoke(methodName, target, target.getClass(), args);
160: }
161:
162: /** Invoke the given method. The target object may be null in which
163: case the target class is used and the method must be a static
164: method.
165:
166: @param methodName The method name
167: @param target The target Object
168: @param targetClass The Class of the target object
169: @param args An array of argument Objects
170: @return The return value
171: @throws IllegalAccessException
172: @throws IllegalArgumentException
173: @throws InvocationTargetException
174: @throws NoSuchMethodException
175: @throws SecurityException
176: */
177:
178: public static Object invoke(String methodName, Object target,
179: Class targetClass, Object[] args)
180: throws IllegalAccessException, IllegalArgumentException,
181: InvocationTargetException, NoSuchMethodException,
182: SecurityException {
183: Class[] paramClasses = new Class[args.length];
184: for (int i = 0; i < args.length; i++) {
185: paramClasses[i] = args[i].getClass();
186: }
187: Method method = getMethod(targetClass, methodName, paramClasses);
188: return invoke(method, target, args);
189: }
190:
191: /** Invoke the given method. This method is a convenience method for
192: invoking single argument methods.
193:
194: @param methodName The method name
195: @param target The target Object
196: @param targetClass The Class of the target object
197: @param arg A single argument
198: @return The return value
199: @throws IllegalAccessException
200: @throws IllegalArgumentException
201: @throws InvocationTargetException
202: @throws NoSuchMethodException
203: @throws SecurityException
204: */
205:
206: public static Object invoke(String methodName, Object target,
207: Class targetClass, Object arg)
208: throws IllegalAccessException, IllegalArgumentException,
209: InvocationTargetException, NoSuchMethodException,
210: SecurityException {
211: if (arg == null) {
212: return invoke(methodName, target, targetClass,
213: EMPTY_OBJECT_ARRAY);
214: } else {
215: Object[] args = new Object[1];
216: args[0] = arg;
217: return invoke(methodName, target, targetClass, args);
218: }
219: }
220:
221: /** Invoke the given method. This method is a convenience method for
222: invoking single argument methods. The argument's class is obtained
223: from the argument object.
224:
225: @param methodName The method name
226: @param target The target Object
227: @param arg A single argument
228: @return The return value
229: @throws IllegalAccessException
230: @throws IllegalArgumentException
231: @throws InvocationTargetException
232: @throws NoSuchMethodException
233: @throws SecurityException
234: */
235:
236: public static Object invokeDeclared(String methodName,
237: Object target, Object arg) throws IllegalAccessException,
238: IllegalArgumentException, InvocationTargetException,
239: NoSuchMethodException, SecurityException {
240: if (arg == null) {
241: return invokeDeclared(methodName, target,
242: EMPTY_OBJECT_ARRAY);
243: } else {
244: Object[] args = new Object[1];
245: args[0] = arg;
246: return invokeDeclared(methodName, target, args);
247: }
248: }
249:
250: /** Invoke the given method. This method is a convenience method for
251: invoking single argument methods. The argument's class is obtained
252: from the argument object.
253:
254: @param methodName The method name
255: @param target The target Object
256: @param args An array of arguments
257: @return The return value
258: @throws IllegalAccessException
259: @throws IllegalArgumentException
260: @throws InvocationTargetException
261: @throws NoSuchMethodException
262: @throws SecurityException
263: */
264:
265: public static Object invokeDeclared(String methodName,
266: Object target, Object[] args)
267: throws IllegalAccessException, IllegalArgumentException,
268: InvocationTargetException, NoSuchMethodException,
269: SecurityException {
270: Class[] paramClasses = new Class[args.length];
271: for (int i = 0; i < args.length; i++) {
272: paramClasses[i] = args[i].getClass();
273: }
274: Method method = getDeclaredMethod(target.getClass(),
275: methodName, paramClasses);
276: return invoke(method, target, args);
277: }
278:
279: /** Get the method with the given name and with a single argument of the
280: type specified by paramClass. The paramClass may be null in which case
281: the method should have no arguments.
282:
283: @param targetClass The target class
284: @param name The method name
285: @param paramClass The single parameter class (may be null)
286: @return The Method
287: @throws SecurityException
288: @throws NoSuchMethodException
289: */
290:
291: public static Method getMethod(Class targetClass, String name,
292: Class paramClass) throws NoSuchMethodException,
293: SecurityException {
294: if (paramClass == null) {
295: return getMethod(targetClass, name, EMPTY_CLASS_ARRAY);
296: } else {
297: Class[] paramClasses = new Class[1];
298: paramClasses[0] = paramClass;
299: return getMethod(targetClass, name, paramClasses);
300: }
301: }
302:
303: /** Get the method with the given name and with arguments of the
304: types specified by paramClasses. If the method is not found
305: then a method which accepts superclasses of the current arguments
306: will be returned, if possible.
307:
308: @param targetClass The target class
309: @param name The method name
310: @param paramClasses An array of parameter classes
311: @return The Method
312: @throws SecurityException
313: @throws NoSuchMethodException
314: */
315:
316: public static Method getMethod(Class targetClass, String name,
317: Class[] paramClasses) throws NoSuchMethodException,
318: SecurityException {
319: Method method = null;
320: try {
321: method = targetClass.getMethod(name, paramClasses);
322: } catch (NoSuchMethodException nsme) {
323: Method[] methods = targetClass.getMethods();
324:
325: OUTER: for (int i = 0; i < methods.length; i++) {
326: if (methods[i].getName().equalsIgnoreCase(name)
327: && methods[i].getParameterTypes().length == paramClasses.length) {
328: Class[] params = methods[i].getParameterTypes();
329: for (int j = 0; j < params.length; j++) {
330: if (!params[j]
331: .isAssignableFrom(paramClasses[j])) {
332: continue OUTER;
333: }
334: }
335: method = methods[i];
336: break;
337: }
338: }
339: if (method == null) {
340: throw nsme;
341: }
342: }
343: return method;
344: }
345:
346: /** Get the declared method with the given name and with a single argument
347: of the type specified by paramClass. The paramClass may be null in
348: which case the method should have no arguments.
349:
350: @param targetClass The target class
351: @param name The method name
352: @param paramClass The single parameter class (may be null)
353: @return The declared Method
354: @throws SecurityException
355: @throws NoSuchMethodException
356: */
357:
358: public static Method getDeclaredMethod(Class targetClass,
359: String name, Class paramClass)
360: throws NoSuchMethodException, SecurityException {
361: if (paramClass == null) {
362: return getDeclaredMethod(targetClass, name,
363: EMPTY_CLASS_ARRAY);
364: } else {
365: Class[] paramClasses = new Class[1];
366: paramClasses[0] = paramClass;
367: return getDeclaredMethod(targetClass, name, paramClasses);
368: }
369: }
370:
371: /** Get the declared method with the given name and with arguments of
372: the types specified by paramClasses.
373:
374: @param targetClass The target class
375: @param name The method name
376: @param paramClasses An array of parameter classes
377: @return The declared Method
378: @throws SecurityException
379: @throws NoSuchMethodException
380: */
381:
382: public static Method getDeclaredMethod(Class targetClass,
383: String name, Class[] paramClasses)
384: throws NoSuchMethodException, SecurityException {
385: return targetClass.getDeclaredMethod(name, paramClasses);
386: }
387:
388: }
|