DefaultObjectFactory.java

  1. /*
  2.  *    Copyright 2009-2021 the original author or authors.
  3.  *
  4.  *    Licensed under the Apache License, Version 2.0 (the "License");
  5.  *    you may not use this file except in compliance with the License.
  6.  *    You may obtain a copy of the License at
  7.  *
  8.  *       http://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  *    Unless required by applicable law or agreed to in writing, software
  11.  *    distributed under the License is distributed on an "AS IS" BASIS,
  12.  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  *    See the License for the specific language governing permissions and
  14.  *    limitations under the License.
  15.  */
  16. package org.apache.ibatis.reflection.factory;

  17. import java.io.Serializable;
  18. import java.lang.reflect.Constructor;
  19. import java.util.ArrayList;
  20. import java.util.Collection;
  21. import java.util.Collections;
  22. import java.util.HashMap;
  23. import java.util.HashSet;
  24. import java.util.List;
  25. import java.util.Map;
  26. import java.util.Optional;
  27. import java.util.Set;
  28. import java.util.SortedSet;
  29. import java.util.TreeSet;
  30. import java.util.stream.Collectors;

  31. import org.apache.ibatis.reflection.ReflectionException;
  32. import org.apache.ibatis.reflection.Reflector;

  33. /**
  34.  * @author Clinton Begin
  35.  */
  36. public class DefaultObjectFactory implements ObjectFactory, Serializable {

  37.   private static final long serialVersionUID = -8855120656740914948L;

  38.   @Override
  39.   public <T> T create(Class<T> type) {
  40.     return create(type, null, null);
  41.   }

  42.   @SuppressWarnings("unchecked")
  43.   @Override
  44.   public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
  45.     Class<?> classToCreate = resolveInterface(type);
  46.     // we know types are assignable
  47.     return (T) instantiateClass(classToCreate, constructorArgTypes, constructorArgs);
  48.   }

  49.   private  <T> T instantiateClass(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
  50.     try {
  51.       Constructor<T> constructor;
  52.       if (constructorArgTypes == null || constructorArgs == null) {
  53.         constructor = type.getDeclaredConstructor();
  54.         try {
  55.           return constructor.newInstance();
  56.         } catch (IllegalAccessException e) {
  57.           if (Reflector.canControlMemberAccessible()) {
  58.             constructor.setAccessible(true);
  59.             return constructor.newInstance();
  60.           } else {
  61.             throw e;
  62.           }
  63.         }
  64.       }
  65.       constructor = type.getDeclaredConstructor(constructorArgTypes.toArray(new Class[0]));
  66.       try {
  67.         return constructor.newInstance(constructorArgs.toArray(new Object[0]));
  68.       } catch (IllegalAccessException e) {
  69.         if (Reflector.canControlMemberAccessible()) {
  70.           constructor.setAccessible(true);
  71.           return constructor.newInstance(constructorArgs.toArray(new Object[0]));
  72.         } else {
  73.           throw e;
  74.         }
  75.       }
  76.     } catch (Exception e) {
  77.       String argTypes = Optional.ofNullable(constructorArgTypes).orElseGet(Collections::emptyList)
  78.           .stream().map(Class::getSimpleName).collect(Collectors.joining(","));
  79.       String argValues = Optional.ofNullable(constructorArgs).orElseGet(Collections::emptyList)
  80.           .stream().map(String::valueOf).collect(Collectors.joining(","));
  81.       throw new ReflectionException("Error instantiating " + type + " with invalid types (" + argTypes + ") or values (" + argValues + "). Cause: " + e, e);
  82.     }
  83.   }

  84.   protected Class<?> resolveInterface(Class<?> type) {
  85.     Class<?> classToCreate;
  86.     if (type == List.class || type == Collection.class || type == Iterable.class) {
  87.       classToCreate = ArrayList.class;
  88.     } else if (type == Map.class) {
  89.       classToCreate = HashMap.class;
  90.     } else if (type == SortedSet.class) { // issue #510 Collections Support
  91.       classToCreate = TreeSet.class;
  92.     } else if (type == Set.class) {
  93.       classToCreate = HashSet.class;
  94.     } else {
  95.       classToCreate = type;
  96.     }
  97.     return classToCreate;
  98.   }

  99.   @Override
  100.   public <T> boolean isCollection(Class<T> type) {
  101.     return Collection.class.isAssignableFrom(type);
  102.   }

  103. }