View Javadoc
1   /**
2    *    Copyright 2009-2015 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  
18  import java.io.Serializable;
19  import java.lang.reflect.Constructor;
20  import java.util.ArrayList;
21  import java.util.Collection;
22  import java.util.HashMap;
23  import java.util.HashSet;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Properties;
27  import java.util.Set;
28  import java.util.SortedSet;
29  import java.util.TreeSet;
30  
31  import org.apache.ibatis.reflection.ReflectionException;
32  
33  /**
34   * @author Clinton Begin
35   */
36  public class DefaultObjectFactory implements ObjectFactory, Serializable {
37  
38    private static final long serialVersionUID = -8855120656740914948L;
39  
40    @Override
41    public <T> T create(Class<T> type) {
42      return create(type, null, null);
43    }
44  
45    @SuppressWarnings("unchecked")
46    @Override
47    public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
48      Class<?> classToCreate = resolveInterface(type);
49      // we know types are assignable
50      return (T) instantiateClass(classToCreate, constructorArgTypes, constructorArgs);
51    }
52  
53    @Override
54    public void setProperties(Properties properties) {
55      // no props for default
56    }
57  
58    <T> T instantiateClass(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
59      try {
60        Constructor<T> constructor;
61        if (constructorArgTypes == null || constructorArgs == null) {
62          constructor = type.getDeclaredConstructor();
63          if (!constructor.isAccessible()) {
64            constructor.setAccessible(true);
65          }
66          return constructor.newInstance();
67        }
68        constructor = type.getDeclaredConstructor(constructorArgTypes.toArray(new Class[constructorArgTypes.size()]));
69        if (!constructor.isAccessible()) {
70          constructor.setAccessible(true);
71        }
72        return constructor.newInstance(constructorArgs.toArray(new Object[constructorArgs.size()]));
73      } catch (Exception e) {
74        StringBuilder argTypes = new StringBuilder();
75        if (constructorArgTypes != null && !constructorArgTypes.isEmpty()) {
76          for (Class<?> argType : constructorArgTypes) {
77            argTypes.append(argType.getSimpleName());
78            argTypes.append(",");
79          }
80          argTypes.deleteCharAt(argTypes.length() - 1); // remove trailing ,
81        }
82        StringBuilder argValues = new StringBuilder();
83        if (constructorArgs != null && !constructorArgs.isEmpty()) {
84          for (Object argValue : constructorArgs) {
85            argValues.append(String.valueOf(argValue));
86            argValues.append(",");
87          }
88          argValues.deleteCharAt(argValues.length() - 1); // remove trailing ,
89        }
90        throw new ReflectionException("Error instantiating " + type + " with invalid types (" + argTypes + ") or values (" + argValues + "). Cause: " + e, e);
91      }
92    }
93  
94    protected Class<?> resolveInterface(Class<?> type) {
95      Class<?> classToCreate;
96      if (type == List.class || type == Collection.class || type == Iterable.class) {
97        classToCreate = ArrayList.class;
98      } else if (type == Map.class) {
99        classToCreate = HashMap.class;
100     } else if (type == SortedSet.class) { // issue #510 Collections Support
101       classToCreate = TreeSet.class;
102     } else if (type == Set.class) {
103       classToCreate = HashSet.class;
104     } else {
105       classToCreate = type;
106     }
107     return classToCreate;
108   }
109 
110   @Override
111   public <T> boolean isCollection(Class<T> type) {
112     return Collection.class.isAssignableFrom(type);
113   }
114 
115 }