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