-
Notifications
You must be signed in to change notification settings - Fork 12
/
CdiProducerBean.java
160 lines (138 loc) · 4.24 KB
/
CdiProducerBean.java
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package org.ndx.aadarchi.maven.cdi.helper.wrappers;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.Set;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import jakarta.enterprise.context.Dependent;
import jakarta.enterprise.context.spi.CreationalContext;
import jakarta.enterprise.inject.Typed;
import jakarta.enterprise.inject.spi.Bean;
import jakarta.enterprise.inject.spi.BeanManager;
import jakarta.enterprise.inject.spi.InjectionPoint;
import jakarta.inject.Qualifier;
public class CdiProducerBean<T> implements Bean<T> {
private Method method;
private Object hostInstance;
private BeanManager beanManager;
private Set<Annotation> qualifiers;
private Set<Type> types;
private Class<?> instanceClass;
public CdiProducerBean(Method method, Object hostInstance, BeanManager beanManager, Type type,
Class<?> instanceClass, Set<Annotation> qualifiers) {
this.method = method;
this.hostInstance = hostInstance;
this.beanManager = beanManager;
this.instanceClass = instanceClass;
this.qualifiers = qualifiers;
this.types = calcBeanTypes(type);
}
private Set<Type> calcBeanTypes(Type implTpye) {
Set<Type> beanTypes = Sets.newHashSet();
if (implTpye instanceof ParameterizedType) {
beanTypes.add((ParameterizedType) implTpye);
} else {
Typed typedAnnotation = ((Class<?>) implTpye).getAnnotation(Typed.class);
if (typedAnnotation != null) {
for (Class<?> cls : typedAnnotation.value()) {
beanTypes.add(cls);
}
} else {
beanTypes.addAll(getTypeClasses((Class<?>) implTpye));
}
}
return beanTypes;
}
private Set<Class<?>> getTypeClasses(Class<?> cls) {
if (cls == null) {
return Collections.emptySet();
}
Set<Class<?>> classes = Sets.newHashSet();
classes.add(cls);
classes.addAll(getTypeClasses(cls.getSuperclass()));
for (Class<?> iface : cls.getInterfaces()) {
classes.addAll(getTypeClasses(iface));
}
return classes;
}
@SuppressWarnings("unchecked")
@Override
public T create(CreationalContext<T> creationalContext) {
Object[] params = new Object[0];
Class<?>[] parameterTypes = this.method.getParameterTypes();
Annotation[][] parameterAnnotations = this.method.getParameterAnnotations();
params = new Object[parameterTypes.length];
for (int i = 0; i < parameterTypes.length; i++) {
Set<Annotation> qualifiers = getCdiQualifiers(parameterAnnotations[i]);
Class<?> paramType = parameterTypes[i];
Set<Bean<?>> beans = this.beanManager.getBeans(paramType,
qualifiers.toArray(new Annotation[qualifiers.size()]));
if (beans.size() == 1) {
Bean<?> bean = Iterables.get(beans, 0);
Object reference = this.beanManager.getReference(bean, paramType,
this.beanManager.createCreationalContext(bean));
params[i] = reference;
} else {
// FIXME handle -> ambiguous results
}
}
T instance = null;
try {
this.method.setAccessible(true);
instance = (T) this.method.invoke(this.hostInstance, params);
} catch (Throwable t) {
t.printStackTrace();
}
return instance;
}
@Override
public void destroy(T instance, CreationalContext<T> creationalContext) {
}
@Override
public Set<Type> getTypes() {
return this.types;
}
@Override
public Set<Annotation> getQualifiers() {
return this.qualifiers;
}
@Override
public Class<? extends Annotation> getScope() {
return Dependent.class;
}
@Override
public String getName() {
return null;
}
@Override
public Set<Class<? extends Annotation>> getStereotypes() {
return Collections.emptySet();
}
@Override
public boolean isAlternative() {
return false;
}
@Override
public Class<?> getBeanClass() {
return this.instanceClass;
}
@Override
public Set<InjectionPoint> getInjectionPoints() {
return Collections.emptySet();
}
public static Set<Annotation> getCdiQualifiers(Annotation[] annotations) {
Set<Annotation> qualifiers = Sets.newHashSet();
for (Annotation annotation : annotations) {
if (annotation.annotationType().isAnnotationPresent(Qualifier.class)) {
qualifiers.add(annotation);
}
}
if (qualifiers.isEmpty()) {
qualifiers.add(new DefaultLiteral());
}
return qualifiers;
}
}