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.guice;
35
36 import info.magnolia.objectfactory.MgnlInstantiationException;
37 import info.magnolia.objectfactory.ParameterInfo;
38 import info.magnolia.objectfactory.ParameterResolver;
39
40 import java.lang.reflect.Modifier;
41 import java.lang.reflect.ParameterizedType;
42 import java.util.List;
43 import java.util.Optional;
44
45 import javax.inject.Inject;
46
47 import com.google.inject.Binding;
48 import com.google.inject.ConfigurationException;
49 import com.google.inject.Injector;
50 import com.google.inject.Key;
51 import com.google.inject.Provider;
52 import com.google.inject.TypeLiteral;
53 import com.google.inject.internal.Annotations;
54 import com.google.inject.internal.Errors;
55 import com.google.inject.internal.ErrorsException;
56
57
58
59
60
61 public class GuiceParameterResolver implements ParameterResolver {
62
63 private final GuiceComponentProvider componentProvider;
64 private final Injector injector;
65
66
67
68
69 @Deprecated
70 public GuiceParameterResolver(Injector injector) {
71 this.componentProvider = null;
72 this.injector = injector;
73 }
74
75 public GuiceParameterResolver(GuiceComponentProvider componentProvider) {
76 this.componentProvider = componentProvider;
77 this.injector = componentProvider.getInjector();
78 }
79
80 @Override
81 public Object resolveParameter(ParameterInfo parameter) {
82
83
84
85
86 Key<?> key = constructGuiceKey(parameter);
87 Binding<?> existingBinding = this.injector.getExistingBinding(key);
88
89 if (existingBinding != null) {
90 return existingBinding.getProvider().get();
91 }
92
93 final Class<?> parameterType = parameter.getParameterType();
94
95
96
97
98
99 if (this.componentProvider != null && parameter.getConstructor().isAnnotationPresent(Inject.class) && !parameterType.isInterface() && !Modifier.isAbstract(parameterType.getModifiers())) {
100 try {
101 return this.componentProvider.newInstance(parameterType);
102 } catch (Exception e) {
103 return UNRESOLVED;
104 }
105 }
106 return UNRESOLVED;
107 }
108
109 private Key<?> constructGuiceKey(ParameterInfo parameter) {
110
111 TypeLiteral<?> declaringType = TypeLiteral.get(parameter.getDeclaringClass());
112 List<TypeLiteral<?>> parameterTypes = declaringType.getParameterTypes(parameter.getConstructor());
113 TypeLiteral<?> parameterType = parameterTypes.get(parameter.getParameterIndex());
114
115 return constructGuiceKey(parameter, parameterType)
116 .filter(key ->
117 GuiceUtils.hasExplicitBindingFor(this.injector, key) ||
118 Provider.class.isAssignableFrom(key.getTypeLiteral().getRawType()) ||
119 javax.inject.Provider.class.isAssignableFrom(key.getTypeLiteral().getRawType()))
120 .orElseGet(() -> {
121 if (parameterType.getType() instanceof ParameterizedType) {
122
123
124
125 return constructGuiceKey(parameter, TypeLiteral.get(parameterType.getRawType())).orElseThrow(() -> new MgnlInstantiationException("Failed to resolve Guice key for generic type [" + parameter.getParameterType() + "]"));
126 }
127 return Key.get(parameterType.getRawType());
128 });
129 }
130
131 private Optional<Key<?>> constructGuiceKey(ParameterInfo parameter, TypeLiteral<?> parameterType) {
132 try {
133
134 Errors errors = new Errors(parameter.getConstructor());
135 return Optional.of(Annotations.getKey(
136 parameterType,
137 parameter.getConstructor(),
138 parameter.getParameterAnnotations(),
139 errors));
140 } catch (ErrorsException | ConfigurationException e) {
141
142 return Optional.empty();
143 } catch (Exception e) {
144 throw new MgnlInstantiationException("Failed to resolve Guice key for [" + parameter.getParameterType() + "]", e);
145 }
146 }
147 }