View Javadoc

1   package org.sf.jlaunchpad.util;
2   
3   import java.lang.reflect.Method;
4   import java.lang.reflect.Modifier;
5   import java.lang.reflect.Field;
6   import java.lang.reflect.InvocationTargetException;
7   
8   /**
9    * This is the class for holding reflection utilities.
10   *
11   * @author Alexander Shvets
12   * @version 1.0 02/19/2006
13   */
14  public class ReflectionUtil {
15  
16    /**
17     * Searches for the "main" method.
18     *
19     * @param clazz the class where we are searching for "main" methd
20     * @return the "main" method
21     */
22    public static Method getMainMethod(final Class clazz) {
23      return getMainMethod(clazz, new Class[]{java.lang.String[].class});
24    }
25  
26    /**
27     * Searches for the "main" method.
28     *
29     * @param clazz the class where we are searching for "main" methd
30     * @return the "main" method
31     * @param secondParameterClass second parameter class
32     */
33    public static Method getMainMethodWithTwoParameters(final Class clazz, final Class secondParameterClass) {
34      return getMainMethod(clazz, new Class[]{java.lang.String[].class, secondParameterClass});
35    }
36  
37    /**
38     * Searches for the "main" method.
39     *
40     * @param clazz the class where we are searching for "main" methd
41     * @return the "main" method
42     * @param paramTypes parameter types
43     */
44    protected static Method getMainMethod(final Class clazz, final Class[] paramTypes) {
45      Method mainMethod = null;
46  
47      final Method[] methods = clazz.getMethods();
48  
49      for (int i = 0; i < methods.length && mainMethod == null; i++) {
50        final Method method = methods[i];
51  
52        if(isCorrectMethod(methods[i], "main", paramTypes)) {
53          mainMethod = method;
54        }
55      }
56  
57      return mainMethod;
58    }
59  
60    /**
61     * Checks if the method has corresponding name and parameter types.
62     *
63     * @param method  the method to check
64     * @param methodName the method name
65     * @param paramTypes the array of parameter types
66     * @return true is the method corresponds the search criteria; false otherwise
67     */
68    private static boolean isCorrectMethod(Method method, String methodName, final Class[] paramTypes) {
69      boolean isCorrect = true;
70  
71      if (method.getName().equals(methodName)) {
72        final int modifiers = method.getModifiers();
73  
74        final boolean correctSignature =
75                Modifier.isStatic(modifiers) &&
76                        Modifier.isPublic(modifiers) &&
77                        (method.getReturnType() == Void.TYPE || method.getReturnType() == Object.class);
78        if (correctSignature) {
79          final Class[] currentParamTypes = method.getParameterTypes();
80  
81          if (currentParamTypes.length == paramTypes.length) {
82            for (int j = 0; j < currentParamTypes.length && isCorrect; j ++) {
83              if (currentParamTypes[j] != paramTypes[j]) {
84                isCorrect = false;
85              }
86            }
87          }
88          else {
89            isCorrect = false;
90          }
91        }
92      }
93      else {
94        isCorrect = false;
95      }
96  
97      return isCorrect;
98    }
99  
100   /**
101    * Tries to launch the class.
102    *
103    * @param mainClass the class to be launched
104    * @param args the list of arguments
105    * @param illegalArgumentMessage the message to be displayed if main method cannot be found
106    * @return result 
107    * @throws IllegalAccessException exception
108    * @throws InvocationTargetException exception
109    */
110   public static Object launchClass(Class mainClass, String[] args, String illegalArgumentMessage)
111           throws IllegalAccessException, InvocationTargetException {
112     final Method mainMethod = getMainMethod(mainClass);
113 
114     return launchClass(mainMethod, new Object[] { args }, illegalArgumentMessage);
115   }
116 
117   /**
118    * Tries to launch the class.
119    *
120    * @param mainMethod main method 
121    * @param args the list of arguments
122    * @param illegalArgumentMessage the message to be displayed if main method cannot be found
123    * @return result
124    * @throws IllegalAccessException exception
125    * @throws InvocationTargetException exception
126    */
127   public static Object launchClass(Method mainMethod, Object[] args, String illegalArgumentMessage)
128           throws IllegalAccessException, InvocationTargetException {
129     if (mainMethod == null) {
130       throw new IllegalArgumentException(illegalArgumentMessage);
131     }
132 
133     //noinspection RedundantArrayCreation
134     return mainMethod.invoke(null, args);
135   }
136 
137   /**
138    * Gets the private filed.
139    *
140    * Required, if you cannot make changes in inheritance and
141    * still need to access the private field.
142    *
143    * @param source the source object
144    * @param name the field name to access
145    * @param clazz the class
146    * @return the private filed
147    * @throws NoSuchFieldException the exception
148    * @throws IllegalAccessException the exception
149    */
150   public static Object getPrivateField(Object source, Class clazz, String name)
151           throws NoSuchFieldException, IllegalAccessException {
152     Field field = clazz.getDeclaredField(name);
153 
154     field.setAccessible(true);
155 
156     Object fieldObject = field.get(source);
157 
158     field.setAccessible(false);
159 
160     return fieldObject;
161   }
162 
163   /**
164    * Sets the private filed.
165    *
166    * Required, if you cannot make changes in inheritance and
167    * still need to access the private field.
168    *
169    * @param source the source object
170    * @param clazz the class
171    * @param name the field name to access
172    * @throws NoSuchFieldException the exception
173    * @throws IllegalAccessException the exception
174    * @param value the value
175    */
176   public static void setPrivateField(Object source, Class clazz, String name, Object value)
177           throws NoSuchFieldException, IllegalAccessException {
178     Field field = clazz.getDeclaredField(name);
179 
180     field.setAccessible(true);
181 
182     field.set(source, value);
183 
184     field.setAccessible(false);
185   }
186 
187   /**
188    * Invokes the private method.
189    *
190    * Required, if you cannot make changes in inheritance and
191    * still need to call the private method.
192    *
193    * @param source the source object
194    * @param parameters the parameters list
195    * @param clazz the source class
196    * @param name the method name
197    * @param parameterTypes the list of parameter types
198    * @return the result of invokation
199    * @throws NoSuchMethodException the exception
200    * @throws IllegalAccessException the exception
201    * @throws InvocationTargetException the exception
202    */
203   public static Object invokePrivateMethod(Object source, Object[] parameters, Class clazz,
204                                            String name, Class[] parameterTypes)
205           throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
206     Method method = clazz.getDeclaredMethod(name, parameterTypes);
207 
208     method.setAccessible(true);
209 
210     Object methodResult = method.invoke(source, parameters);
211 
212     method.setAccessible(false);
213 
214     return methodResult;
215   }
216 
217 }