All Downloads are FREE. Search and download functionalities are using the official Maven repository.

mockit.internal.reflection.ConstructorReflection Maven / Gradle / Ivy

Go to download

JMockit is a Java toolkit for automated developer testing. It contains mocking/faking APIs and a code coverage tool, supporting both JUnit and TestNG. The mocking APIs allow all kinds of Java code, without testability restrictions, to be tested in isolation from selected dependencies.

There is a newer version: 1.49
Show newest version
/*
 * Copyright (c) 2006 JMockit developers
 * This file is subject to the terms of the MIT license (see LICENSE.txt).
 */
package mockit.internal.reflection;

import java.lang.reflect.*;
import javax.annotation.*;

import static java.lang.reflect.Modifier.isAbstract;

import mockit.internal.classGeneration.*;
import mockit.internal.reflection.EmptyProxy.*;
import mockit.internal.util.*;
import static mockit.internal.reflection.ParameterReflection.*;
import static mockit.internal.util.Utilities.ensureThatMemberIsAccessible;

public final class ConstructorReflection
{
   private static final Constructor OBJECT_CONSTRUCTOR;
   static {
      try { OBJECT_CONSTRUCTOR = Object.class.getConstructor(); }
      catch (NoSuchMethodException e) { throw new RuntimeException(e); }
   }

   private ConstructorReflection() {}

   @Nonnull
   static  Constructor findSpecifiedConstructor(@Nonnull Class theClass, @Nonnull Class[] paramTypes) {
      for (Constructor declaredConstructor : theClass.getDeclaredConstructors()) {
         Class[] declaredParameterTypes = declaredConstructor.getParameterTypes();
         int firstRealParameter = indexOfFirstRealParameter(declaredParameterTypes, paramTypes);

         if (firstRealParameter >= 0 && matchesParameterTypes(declaredParameterTypes, paramTypes, firstRealParameter)) {
            //noinspection unchecked
            return (Constructor) declaredConstructor;
         }
      }

      String paramTypesDesc = getParameterTypesDescription(paramTypes);

      throw new IllegalArgumentException("Specified constructor not found: " + theClass.getSimpleName() + paramTypesDesc);
   }

   @Nonnull
   public static  T invoke(@Nonnull Constructor constructor, @Nonnull Object... initArgs) {
      ensureThatMemberIsAccessible(constructor);

      try {
         return constructor.newInstance(initArgs);
      }
      catch (InstantiationException | IllegalAccessException e) {
         throw new RuntimeException(e);
      }
      catch (InvocationTargetException e) {
         Throwable cause = e.getCause();

         if (cause instanceof Error) {
            throw (Error) cause;
         }
         else if (cause instanceof RuntimeException) {
            throw (RuntimeException) cause;
         }
         else {
            ThrowOfCheckedException.doThrow((Exception) cause);
            throw new IllegalStateException("Should never get here", cause);
         }
      }
   }

   @Nonnull
   public static  T newInstance(@Nonnull Class aClass, @Nullable Object... nonNullArgs) {
      if (nonNullArgs == null) {
         throw invalidArguments();
      }

      Class[] argTypes = getArgumentTypesFromArgumentValues(nonNullArgs);
      Constructor constructor = findCompatibleConstructor(aClass, argTypes);
      return invoke(constructor, nonNullArgs);
   }

   @Nonnull
   private static  Constructor findCompatibleConstructor(@Nonnull Class theClass, @Nonnull Class[] argTypes) {
      Constructor found = null;
      Class[] foundParameters = null;
      Constructor[] declaredConstructors = theClass.getDeclaredConstructors();

      for (Constructor declaredConstructor : declaredConstructors) {
         Class[] declaredParamTypes = declaredConstructor.getParameterTypes();
         int firstRealParameter = indexOfFirstRealParameter(declaredParamTypes, argTypes);

         if (
            firstRealParameter >= 0 && (
               matchesParameterTypes(declaredParamTypes, argTypes, firstRealParameter) ||
               acceptsArgumentTypes(declaredParamTypes, argTypes, firstRealParameter)
            ) && (
               found == null || hasMoreSpecificTypes(declaredParamTypes, foundParameters)
            )
         ) {
            //noinspection unchecked
            found = (Constructor) declaredConstructor;
            foundParameters = declaredParamTypes;
         }
      }

      if (found != null) {
         return found;
      }

      Class declaringClass = theClass.getDeclaringClass();
      Class[] paramTypes = declaredConstructors[0].getParameterTypes();

      if (paramTypes.length > argTypes.length && paramTypes[0] == declaringClass) {
         throw new IllegalArgumentException("Invalid instantiation of inner class");
      }

      String argTypesDesc = getParameterTypesDescription(argTypes);
      throw new IllegalArgumentException("No compatible constructor found: " + theClass.getSimpleName() + argTypesDesc);
   }

   @Nonnull
   public static  T newInstanceUsingDefaultConstructor(@Nonnull Class aClass) {
      try {
         //noinspection ClassNewInstance
         return aClass.newInstance();
      }
      catch (InstantiationException ie) {
         throw new RuntimeException(ie);
      }
      catch (IllegalAccessException ignore) {
         return newInstance(aClass, (Object[]) NO_PARAMETERS);
      }
   }

   @Nullable
   public static  T newInstanceUsingDefaultConstructorIfAvailable(@Nonnull Class aClass) {
      try {
         //noinspection ClassNewInstance
         return aClass.newInstance();
      }
      catch (InstantiationException | IllegalAccessException ignore) { return null; }
   }

   @Nullable
   public static  T newInstanceUsingPublicConstructorIfAvailable(
      @Nonnull Class aClass, @Nonnull Class[] parameterTypes, @Nonnull Object... initArgs
   ) {
      Constructor publicConstructor;
      try { publicConstructor = aClass.getConstructor(parameterTypes); }
      catch (NoSuchMethodException ignore) { return null; }

      return invoke(publicConstructor, initArgs);
   }

   @SuppressWarnings({"UnnecessaryFullyQualifiedName", "UseOfSunClasses"})
   private static final sun.reflect.ReflectionFactory REFLECTION_FACTORY = sun.reflect.ReflectionFactory.getReflectionFactory();

   @Nonnull
   public static  T newUninitializedConcreteClassInstance(@Nonnull Class aClass) {
      try {
         Constructor fakeConstructor = REFLECTION_FACTORY.newConstructorForSerialization(aClass, OBJECT_CONSTRUCTOR);

         if (fakeConstructor == null) { // can happen on Java 9
            //noinspection ConstantConditions
            return null;
         }

         @SuppressWarnings("unchecked") T newInstance = (T) fakeConstructor.newInstance();
         return newInstance;
      }
      catch (NoClassDefFoundError | ExceptionInInitializerError e) {
         StackTrace.filterStackTrace(e);
         e.printStackTrace();
         throw e;
      }
      catch (InstantiationException | IllegalAccessException e) { throw new RuntimeException(e); }
      catch (InvocationTargetException e) { throw new RuntimeException(e.getCause()); }
   }

   @Nonnull
   public static  T newUninitializedInstance(@Nonnull Class classToInstantiate) {
      if (classToInstantiate.isInterface()) {
         T instance = Impl.newEmptyProxy(classToInstantiate.getClassLoader(), classToInstantiate);
         return instance;
      }

      if (isAbstract(classToInstantiate.getModifiers())) {
         classToInstantiate = new ConcreteSubclass(classToInstantiate).generateClass();
      }

      return newUninitializedConcreteClassInstance(classToInstantiate);
   }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy