View Javadoc
1   package org.apache.maven.surefire.api.util;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.lang.reflect.Constructor;
23  import java.lang.reflect.InvocationTargetException;
24  import java.lang.reflect.Method;
25  
26  /**
27   * @author Kristian Rosenvold
28   */
29  public final class ReflectionUtils
30  {
31      private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
32      private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
33  
34      private ReflectionUtils()
35      {
36          throw new IllegalStateException( "no instantiable constructor" );
37      }
38  
39      public static Method getMethod( Object instance, String methodName, Class<?>... parameters )
40      {
41          return getMethod( instance.getClass(), methodName, parameters );
42      }
43  
44      public static Method getMethod( Class<?> clazz, String methodName, Class<?>... parameters )
45      {
46          try
47          {
48              return clazz.getMethod( methodName, parameters );
49          }
50          catch ( NoSuchMethodException e )
51          {
52              throw new RuntimeException( "When finding method " + methodName, e );
53          }
54      }
55  
56      public static Method tryGetMethod( Class<?> clazz, String methodName, Class<?>... parameters )
57      {
58          try
59          {
60              return clazz.getMethod( methodName, parameters );
61          }
62          catch ( NoSuchMethodException e )
63          {
64              return null;
65          }
66      }
67  
68      public static Object invokeGetter( Object instance, String methodName )
69      {
70          return invokeGetter( instance.getClass(), instance, methodName );
71      }
72  
73      public static Object invokeGetter( Class<?> instanceType, Object instance, String methodName )
74      {
75          Method method = getMethod( instanceType, methodName );
76          return invokeMethodWithArray( instance, method );
77      }
78  
79      public static Constructor<?> getConstructor( Class<?> clazz, Class<?>... arguments )
80      {
81          try
82          {
83              return clazz.getConstructor( arguments );
84          }
85          catch ( NoSuchMethodException e )
86          {
87              throw new SurefireReflectionException( e );
88          }
89      }
90  
91      public static Object newInstance( Constructor<?> constructor, Object... params )
92      {
93          try
94          {
95              return constructor.newInstance( params );
96          }
97          catch ( ReflectiveOperationException e )
98          {
99              throw new SurefireReflectionException( e );
100         }
101     }
102 
103     public static <T> T instantiate( ClassLoader classLoader, String classname, Class<T> returnType )
104     {
105         try
106         {
107             Class<?> clazz = loadClass( classLoader, classname );
108             return returnType.cast( clazz.newInstance() );
109         }
110         catch ( ReflectiveOperationException e )
111         {
112             throw new SurefireReflectionException( e );
113         }
114     }
115 
116     public static Object instantiateOneArg( ClassLoader classLoader, String className, Class<?> param1Class,
117                                             Object param1 )
118     {
119         try
120         {
121             Class<?> aClass = loadClass( classLoader, className );
122             Constructor<?> constructor = getConstructor( aClass, param1Class );
123             return constructor.newInstance( param1 );
124         }
125         catch ( InvocationTargetException e )
126         {
127             throw new SurefireReflectionException( e.getTargetException() );
128         }
129         catch ( ReflectiveOperationException e )
130         {
131             throw new SurefireReflectionException( e );
132         }
133     }
134 
135     public static void invokeSetter( Object o, String name, Class<?> value1clazz, Object value )
136     {
137         Method setter = getMethod( o, name, value1clazz );
138         invokeSetter( o, setter, value );
139     }
140 
141     public static Object invokeSetter( Object target, Method method, Object value )
142     {
143         return invokeMethodWithArray( target, method, value );
144     }
145 
146     public static Object invokeMethodWithArray( Object target, Method method, Object... args )
147     {
148         try
149         {
150             return method.invoke( target, args );
151         }
152         catch ( IllegalAccessException e )
153         {
154             throw new SurefireReflectionException( e );
155         }
156         catch ( InvocationTargetException e )
157         {
158             throw new SurefireReflectionException( e.getTargetException() );
159         }
160     }
161 
162     public static Object invokeMethodWithArray2( Object target, Method method, Object... args )
163         throws InvocationTargetException
164     {
165         try
166         {
167             return method.invoke( target, args );
168         }
169         catch ( IllegalAccessException e )
170         {
171             throw new SurefireReflectionException( e );
172         }
173     }
174 
175     public static Object instantiateObject( String className, Class<?>[] types, Object[] params, ClassLoader cl )
176     {
177         Class<?> clazz = loadClass( cl, className );
178         final Constructor<?> constructor = getConstructor( clazz, types );
179         return newInstance( constructor, params );
180     }
181 
182     @SuppressWarnings( "checkstyle:emptyblock" )
183     public static Class<?> tryLoadClass( ClassLoader classLoader, String className )
184     {
185         try
186         {
187             return classLoader.loadClass( className );
188         }
189         catch ( NoClassDefFoundError | ClassNotFoundException ignore )
190         {
191         }
192         return null;
193     }
194 
195     public static Class<?> loadClass( ClassLoader classLoader, String className )
196     {
197         try
198         {
199             return classLoader.loadClass( className );
200         }
201         catch ( NoClassDefFoundError | ClassNotFoundException e )
202         {
203             throw new SurefireReflectionException( e );
204         }
205     }
206 
207     public static Class<?> reloadClass( ClassLoader classLoader, Object source )
208             throws ReflectiveOperationException
209     {
210         return classLoader.loadClass( source.getClass().getName() );
211     }
212 
213     /**
214      * Invoker of public static no-argument method.
215      *
216      * @param clazz         class on which public static no-argument {@code methodName} is invoked
217      * @param methodName    public static no-argument method to be called
218      * @param parameterTypes    method parameter types
219      * @param parameters    method parameters
220      * @return value returned by {@code methodName}
221      * @throws RuntimeException if no such method found
222      * @throws SurefireReflectionException if the method could not be called or threw an exception.
223      * It has original cause Exception.
224      */
225     public static Object invokeStaticMethod( Class<?> clazz, String methodName,
226                                              Class<?>[] parameterTypes, Object[] parameters )
227     {
228         if ( parameterTypes.length != parameters.length )
229         {
230             throw new IllegalArgumentException( "arguments length do not match" );
231         }
232         Method method = getMethod( clazz, methodName, parameterTypes );
233         return invokeMethodWithArray( null, method, parameters );
234     }
235 
236     /**
237      * Method chain invoker.
238      *
239      * @param classesChain        classes to invoke on method chain
240      * @param noArgMethodNames    chain of public methods to call
241      * @param fallback            returned value if a chain could not be invoked due to an error
242      * @return successfully returned value from the last method call; {@code fallback} otherwise
243      * @throws IllegalArgumentException if {@code classes} and {@code noArgMethodNames} have different array length
244      */
245     public static Object invokeMethodChain( Class<?>[] classesChain, String[] noArgMethodNames, Object fallback )
246     {
247         if ( classesChain.length != noArgMethodNames.length )
248         {
249             throw new IllegalArgumentException( "arrays must have the same length" );
250         }
251         Object obj = null;
252         try
253         {
254             for ( int i = 0, len = noArgMethodNames.length; i < len; i++ )
255             {
256                 if ( i == 0 )
257                 {
258                     obj = invokeStaticMethod( classesChain[i], noArgMethodNames[i],
259                                                     EMPTY_CLASS_ARRAY, EMPTY_OBJECT_ARRAY );
260                 }
261                 else
262                 {
263                     Method method = getMethod( classesChain[i], noArgMethodNames[i] );
264                     obj = invokeMethodWithArray( obj, method );
265                 }
266             }
267             return obj;
268         }
269         catch ( RuntimeException e )
270         {
271             return fallback;
272         }
273     }
274 }