View Javadoc
1   /*
2    * Copyright (c) 2006 JMockit developers
3    * This file is subject to the terms of the MIT license (see LICENSE.txt).
4    */
5   package mockit.internal.reflection;
6   
7   import static mockit.internal.reflection.ParameterReflection.getParameterTypesDescription;
8   import static mockit.internal.reflection.ParameterReflection.indexOfFirstRealParameter;
9   import static mockit.internal.reflection.ParameterReflection.matchesParameterTypes;
10  import static mockit.internal.util.Utilities.ensureThatMemberIsAccessible;
11  
12  import edu.umd.cs.findbugs.annotations.NonNull;
13  import edu.umd.cs.findbugs.annotations.Nullable;
14  
15  import java.lang.reflect.Constructor;
16  import java.lang.reflect.InvocationTargetException;
17  
18  import org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator;
19  
20  public final class ConstructorReflection {
21      private ConstructorReflection() {
22      }
23  
24      @NonNull
25      static <T> Constructor<T> findSpecifiedConstructor(@NonNull Class<?> theClass, @NonNull Class<?>[] paramTypes) {
26          for (Constructor<?> declaredConstructor : theClass.getDeclaredConstructors()) {
27              Class<?>[] declaredParameterTypes = declaredConstructor.getParameterTypes();
28              int firstRealParameter = indexOfFirstRealParameter(declaredParameterTypes, paramTypes);
29  
30              if (firstRealParameter >= 0
31                      && matchesParameterTypes(declaredParameterTypes, paramTypes, firstRealParameter)) {
32                  // noinspection unchecked
33                  return (Constructor<T>) declaredConstructor;
34              }
35          }
36  
37          String paramTypesDesc = getParameterTypesDescription(paramTypes);
38  
39          throw new IllegalArgumentException(
40                  "Specified constructor not found: " + theClass.getSimpleName() + paramTypesDesc);
41      }
42  
43      @NonNull
44      public static <T> T invokeAccessible(@NonNull Constructor<T> constructor, @NonNull Object... initArgs) {
45          if (!constructor.isAccessible()) {
46              constructor.setAccessible(true);
47          }
48          try {
49              return constructor.newInstance(initArgs);
50          } catch (InstantiationException | IllegalAccessException e) {
51              throw new RuntimeException(e);
52          } catch (InvocationTargetException e) {
53              Throwable cause = e.getCause();
54  
55              if (cause instanceof Error) {
56                  throw (Error) cause;
57              }
58              if (cause instanceof RuntimeException) {
59                  throw (RuntimeException) cause;
60              }
61              ThrowOfCheckedException.doThrow((Exception) cause);
62              throw new IllegalStateException("Should never get here", cause);
63          }
64      }
65  
66      public static void newInstanceUsingCompatibleConstructor(@NonNull Class<?> aClass, @NonNull String argument)
67              throws ReflectiveOperationException {
68          Constructor<?> constructor = aClass.getDeclaredConstructor(String.class);
69          ensureThatMemberIsAccessible(constructor);
70          constructor.newInstance(argument);
71      }
72  
73      @NonNull
74      public static <T> T newInstanceUsingDefaultConstructor(@NonNull Class<T> aClass) {
75          try {
76              Constructor<T> constructor = aClass.getDeclaredConstructor();
77              ensureThatMemberIsAccessible(constructor);
78              return constructor.newInstance();
79          } catch (NoSuchMethodException | InstantiationException | IllegalAccessException e) {
80              throw new RuntimeException(e);
81          } catch (InvocationTargetException e) {
82              throw new RuntimeException(e.getTargetException());
83          }
84      }
85  
86      @Nullable
87      public static <T> T newInstanceUsingDefaultConstructorIfAvailable(@NonNull Class<T> aClass) {
88          try {
89              Constructor<T> constructor = aClass.getDeclaredConstructor();
90              return constructor.newInstance();
91          } catch (NoSuchMethodException | InstantiationException | IllegalAccessException
92                  | InvocationTargetException ignore) {
93              return null;
94          }
95      }
96  
97      @Nullable
98      public static <T> T newInstanceUsingPublicConstructorIfAvailable(@NonNull Class<T> aClass,
99              @NonNull Class<?>[] parameterTypes, @NonNull Object... initArgs) {
100         Constructor<T> publicConstructor;
101         try {
102             publicConstructor = aClass.getConstructor(parameterTypes);
103         } catch (NoSuchMethodException ignore) {
104             return null;
105         }
106 
107         return invokeAccessible(publicConstructor, initArgs);
108     }
109 
110     @NonNull
111     public static <T> T newInstanceUsingPublicDefaultConstructor(@NonNull Class<T> aClass) {
112         Constructor<T> publicConstructor;
113         try {
114             publicConstructor = aClass.getConstructor();
115         } catch (NoSuchMethodException e) {
116             throw new RuntimeException(e);
117         }
118 
119         return invokeAccessible(publicConstructor);
120     }
121 
122     @NonNull
123     public static <T> T newUninitializedInstance(@NonNull Class<T> aClass) {
124         SunReflectionFactoryInstantiator<T> ref = new SunReflectionFactoryInstantiator<>(aClass);
125         return ref.newInstance();
126     }
127 }