1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.objectfactory;
35
36 import java.lang.reflect.Constructor;
37 import java.lang.reflect.InvocationTargetException;
38 import java.lang.reflect.Modifier;
39 import javax.inject.Inject;
40
41
42
43
44
45
46
47
48 public class ObjectManufacturer {
49
50
51
52
53
54
55
56
57 public Object newInstance(Class<?> clazz, ParameterResolver... parameterResolvers) {
58
59 Constructor<?>[] constructors = clazz.getDeclaredConstructors();
60
61 Constructor<?> selectedConstructor = null;
62 for (Constructor<?> constructor : constructors) {
63 if (constructor.isAnnotationPresent(Inject.class)) {
64 if (selectedConstructor != null) {
65 throw new MgnlInstantiationException("Only one constructor can use @Inject [" + clazz + "]");
66 }
67 selectedConstructor = constructor;
68 }
69 }
70 if (selectedConstructor != null) {
71 selectedConstructor.setAccessible(true);
72 Object[] parameters = resolveParameters(selectedConstructor, parameterResolvers);
73 if (parameters == null) {
74 throw new MgnlInstantiationException("Unable to resolve parameters for constructor " + selectedConstructor);
75 }
76 return newInstance(selectedConstructor, parameters);
77 }
78
79
80 int bestScore = -1;
81 Object[] bestParameters = null;
82 for (Constructor<?> constructor : constructors) {
83 if (!Modifier.isPublic(constructor.getModifiers())) {
84 continue;
85 }
86 int score = constructor.getParameterTypes().length;
87 if (score < bestScore) {
88 continue;
89 }
90 Object[] parameters = resolveParameters(constructor, parameterResolvers);
91 if (parameters == null) {
92 continue;
93 }
94 selectedConstructor = constructor;
95 bestScore = score;
96 bestParameters = parameters;
97 }
98 if (selectedConstructor != null) {
99 return newInstance(selectedConstructor, bestParameters);
100 }
101 throw new MgnlInstantiationException("No suitable constructor found for class [" + clazz + "]");
102 }
103
104 private Object newInstance(Constructor constructor, Object[] parameters) {
105 try {
106 return constructor.newInstance(parameters);
107 } catch (InstantiationException e) {
108 throw new MgnlInstantiationException(e);
109 } catch (IllegalAccessException e) {
110 throw new MgnlInstantiationException(e);
111 } catch (InvocationTargetException e) {
112 throw new MgnlInstantiationException(e);
113 }
114 }
115
116 private Object[] resolveParameters(Constructor<?> constructor, ParameterResolver[] parameterResolvers) {
117 Object[] parameters = new Object[constructor.getParameterTypes().length];
118 for (int parameterIndex = 0; parameterIndex < parameters.length; parameterIndex++) {
119 ParameterInfo constructorParameter = new ParameterInfo(constructor, parameterIndex);
120 Object parameter = resolveParameter(constructorParameter, parameterResolvers);
121 if (parameter == ParameterResolver.UNRESOLVED) {
122 return null;
123 }
124 parameters[parameterIndex] = parameter;
125 }
126 return parameters;
127 }
128
129 private Object resolveParameter(ParameterInfo constructorParameter, ParameterResolver[] parameterResolvers) {
130 for (ParameterResolver parameterResolver : parameterResolvers) {
131 Object parameter = parameterResolver.resolveParameter(constructorParameter);
132 if (parameter != ParameterResolver.UNRESOLVED) {
133 return parameter;
134 }
135 }
136 return ParameterResolver.UNRESOLVED;
137 }
138
139 }