Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
BeanProvider |
|
| 2.6666666666666665;2.667 |
1 | /* | |
2 | * Licensed to the Apache Software Foundation (ASF) under one | |
3 | * or more contributor license agreements. See the NOTICE file | |
4 | * distributed with this work for additional information | |
5 | * regarding copyright ownership. The ASF licenses this file | |
6 | * to you under the Apache License, Version 2.0 (the | |
7 | * "License"); you may not use this file except in compliance | |
8 | * with the License. You may obtain a copy of the License at | |
9 | * | |
10 | * http://www.apache.org/licenses/LICENSE-2.0 | |
11 | * | |
12 | * Unless required by applicable law or agreed to in writing, | |
13 | * software distributed under the License is distributed on an | |
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
15 | * KIND, either express or implied. See the License for the | |
16 | * specific language governing permissions and limitations | |
17 | * under the License. | |
18 | */ | |
19 | package org.apache.myfaces.cdi.util; | |
20 | ||
21 | import javax.enterprise.context.spi.CreationalContext; | |
22 | import javax.enterprise.inject.Typed; | |
23 | import javax.enterprise.inject.spi.Bean; | |
24 | import javax.enterprise.inject.spi.BeanManager; | |
25 | import java.lang.annotation.Annotation; | |
26 | import java.util.Arrays; | |
27 | import java.util.Set; | |
28 | ||
29 | /** | |
30 | * <p>This class contains utility methods to resolve contextual references | |
31 | * in situations where no injection is available because the | |
32 | * current class is not managed by the CDI Container. This can happen | |
33 | * in e.g. a JPA-2.0 EntityListener, a ServletFilter, a Spring managed | |
34 | * Bean, etc.</p> | |
35 | * | |
36 | * <p><b>Attention:</b> This method is intended for being used in user code at runtime. | |
37 | * If this method gets used during Container boot (in an Extension), non-portable | |
38 | * behaviour results. The CDI specification only allows injection of the | |
39 | * BeanManager during CDI-Container boot time.</p> | |
40 | * | |
41 | * @see BeanManagerProvider | |
42 | */ | |
43 | @Typed() | |
44 | public final class BeanProvider | |
45 | { | |
46 | //private static final Logger LOG = Logger.getLogger(BeanProvider.class.getName()); | |
47 | ||
48 | /* | |
49 | private static final boolean LOG_DEPENDENT_WARNINGS; | |
50 | static { | |
51 | ProjectStage ps = ProjectStageProducer.getInstance().getProjectStage(); | |
52 | LOG_DEPENDENT_WARNINGS = ps.equals(ProjectStage.Development) || ps.equals(ProjectStage.UnitTest); | |
53 | }*/ | |
54 | ||
55 | private BeanProvider() | |
56 | 0 | { |
57 | // this is a utility class which doesn't get instantiated. | |
58 | 0 | } |
59 | ||
60 | /** | |
61 | * <p>Get a Contextual Reference by its type and qualifiers. | |
62 | * You can use this method to get contextual references of a given type. | |
63 | * A 'Contextual Reference' is a proxy which will automatically resolve | |
64 | * the correct contextual instance when you access any method.</p> | |
65 | * | |
66 | * <p><b>Attention:</b> You shall not use this method to manually resolve a | |
67 | * @Dependent bean! The reason is that this contextual instances do usually | |
68 | * live in the well-defined lifecycle of their injection point (the bean they got | |
69 | * injected into). But if we manually resolve a @Dependent bean, then it does <b>not</b> | |
70 | * belong to such a well defined lifecycle (because @Dependent it is not | |
71 | * @NormalScoped) and thus will not automatically be | |
72 | * destroyed at the end of the lifecycle. You need to manually destroy this contextual instance via | |
73 | * {@link javax.enterprise.context.spi.Contextual#destroy(Object, javax.enterprise.context.spi.CreationalContext)}. | |
74 | * Thus you also need to manually store the CreationalContext and the Bean you | |
75 | * used to create the contextual instance which this method will not provide.</p> | |
76 | * | |
77 | * @param type the type of the bean in question | |
78 | * @param qualifiers additional qualifiers which further distinct the resolved bean | |
79 | * @param <T> target type | |
80 | * @return the resolved Contextual Reference | |
81 | * @throws IllegalStateException if the bean could not be found. | |
82 | * @see #getContextualReference(Class, boolean, Annotation...) | |
83 | */ | |
84 | /* | |
85 | public static <T> T getContextualReference(Class<T> type, Annotation... qualifiers) | |
86 | { | |
87 | return getContextualReference(type, false, qualifiers); | |
88 | }*/ | |
89 | ||
90 | /** | |
91 | * {@link #getContextualReference(Class, Annotation...)} which returns <code>null</code> if the | |
92 | * 'optional' parameter is set to <code>true</code>. | |
93 | * | |
94 | * @param type the type of the bean in question | |
95 | * @param optional if <code>true</code> it will return <code>null</code> if no bean could be found or created. | |
96 | * Otherwise it will throw an {@code IllegalStateException} | |
97 | * @param qualifiers additional qualifiers which further distinct the resolved bean | |
98 | * @param <T> target type | |
99 | * @return the resolved Contextual Reference | |
100 | * @see #getContextualReference(Class, Annotation...) | |
101 | */ | |
102 | /* | |
103 | public static <T> T getContextualReference(Class<T> type, boolean optional, Annotation... qualifiers) | |
104 | { | |
105 | BeanManager beanManager = getBeanManager(); | |
106 | ||
107 | return getContextualReference(beanManager, type, optional, qualifiers); | |
108 | }*/ | |
109 | ||
110 | /** | |
111 | * {@link #getContextualReference(Class, Annotation...)} which returns <code>null</code> if the | |
112 | * 'optional' parameter is set to <code>true</code>. | |
113 | * This method is intended for usage where the BeanManger is known, e.g. in Extensions. | |
114 | * | |
115 | * @param beanManager the BeanManager to use | |
116 | * @param type the type of the bean in question | |
117 | * @param optional if <code>true</code> it will return <code>null</code> if no bean could be found or created. | |
118 | * Otherwise it will throw an {@code IllegalStateException} | |
119 | * @param qualifiers additional qualifiers which further distinct the resolved bean | |
120 | * @param <T> target type | |
121 | * @return the resolved Contextual Reference | |
122 | * @see #getContextualReference(Class, Annotation...) | |
123 | */ | |
124 | public static <T> T getContextualReference(BeanManager beanManager, | |
125 | Class<T> type, | |
126 | boolean optional, | |
127 | Annotation... qualifiers) | |
128 | { | |
129 | 0 | Set<Bean<?>> beans = beanManager.getBeans(type, qualifiers); |
130 | ||
131 | 0 | if (beans == null || beans.isEmpty()) |
132 | { | |
133 | 0 | if (optional) |
134 | { | |
135 | 0 | return null; |
136 | } | |
137 | ||
138 | 0 | throw new IllegalStateException("Could not find beans for Type=" + type |
139 | + " and qualifiers:" + Arrays.toString(qualifiers)); | |
140 | } | |
141 | ||
142 | 0 | return getContextualReference(type, beanManager, beans); |
143 | } | |
144 | ||
145 | /** | |
146 | * <p>Get a Contextual Reference by its EL Name. | |
147 | * This only works for beans with the @Named annotation.</p> | |
148 | * | |
149 | * <p><b>Attention:</b> please see the notes on manually resolving @Dependent bean | |
150 | * in {@link #getContextualReference(Class, boolean, java.lang.annotation.Annotation...)}!</p> | |
151 | * | |
152 | * @param name the EL name of the bean | |
153 | * @return the resolved Contextual Reference | |
154 | * @throws IllegalStateException if the bean could not be found. | |
155 | * @see #getContextualReference(String, boolean) | |
156 | */ | |
157 | /* | |
158 | public static Object getContextualReference(String name) | |
159 | { | |
160 | return getContextualReference(name, false); | |
161 | }*/ | |
162 | ||
163 | /** | |
164 | * <p>Get a Contextual Reference by its EL Name. | |
165 | * This only works for beans with the @Named annotation.</p> | |
166 | * | |
167 | * <p><b>Attention:</b> please see the notes on manually resolving @Dependent bean | |
168 | * in {@link #getContextualReference(Class, boolean, java.lang.annotation.Annotation...)}!</p> | |
169 | * | |
170 | * @param name the EL name of the bean | |
171 | * @param optional if <code>true</code> it will return <code>null</code> if no bean could be found or created. | |
172 | * Otherwise it will throw an {@code IllegalStateException} | |
173 | * @return the resolved Contextual Reference | |
174 | */ | |
175 | /* | |
176 | public static Object getContextualReference(String name, boolean optional) | |
177 | { | |
178 | return getContextualReference(name, optional, Object.class); | |
179 | }*/ | |
180 | ||
181 | /** | |
182 | * <p>Get a Contextual Reference by its EL Name. | |
183 | * This only works for beans with the @Named annotation.</p> | |
184 | * | |
185 | * <p><b>Attention:</b> please see the notes on manually resolving @Dependent bean | |
186 | * in {@link #getContextualReference(Class, boolean, java.lang.annotation.Annotation...)}!</p> | |
187 | * | |
188 | * | |
189 | * @param name the EL name of the bean | |
190 | * @param optional if <code>true</code> it will return <code>null</code> if no bean could be found or created. | |
191 | * Otherwise it will throw an {@code IllegalStateException} | |
192 | * @param type the type of the bean in question - use {@link #getContextualReference(String, boolean)} | |
193 | * if the type is unknown e.g. in dyn. use-cases | |
194 | * @param <T> target type | |
195 | * @return the resolved Contextual Reference | |
196 | */ | |
197 | /* | |
198 | public static <T> T getContextualReference(String name, boolean optional, Class<T> type) | |
199 | { | |
200 | BeanManager beanManager = getBeanManager(); | |
201 | Set<Bean<?>> beans = beanManager.getBeans(name); | |
202 | ||
203 | if (beans == null || beans.isEmpty()) | |
204 | { | |
205 | if (optional) | |
206 | { | |
207 | return null; | |
208 | } | |
209 | ||
210 | throw new IllegalStateException("Could not find beans for Type=" + type | |
211 | + " and name:" + name); | |
212 | } | |
213 | ||
214 | return getContextualReference(type, beanManager, beans); | |
215 | }*/ | |
216 | ||
217 | /** | |
218 | * Get the Contextual Reference for the given bean. | |
219 | * | |
220 | * @param type the type of the bean in question | |
221 | * @param bean bean-definition for the contextual-reference | |
222 | * @param <T> target type | |
223 | * @return the resolved Contextual Reference | |
224 | */ | |
225 | /* | |
226 | public static <T> T getContextualReference(Class<T> type, Bean<T> bean) | |
227 | { | |
228 | return getContextualReference(type, getBeanManager(), bean); | |
229 | }*/ | |
230 | ||
231 | /* | |
232 | private static <T> T getContextualReference(Class<T> type, BeanManager beanManager, Bean<?> bean) | |
233 | { | |
234 | //noinspection unchecked | |
235 | return getContextualReference(type, beanManager, new HashSet<Bean<?>>((Collection) Arrays.asList(bean))); | |
236 | } | |
237 | */ | |
238 | ||
239 | /** | |
240 | * <p>Get a list of Contextual References by type independent of the qualifier | |
241 | * (including dependent scoped beans). | |
242 | * | |
243 | * You can use this method to get all contextual references of a given type. | |
244 | * A 'Contextual Reference' is a proxy which will automatically resolve | |
245 | * the correct contextual instance when you access any method.</p> | |
246 | * | |
247 | * <p><b>Attention:</b> please see the notes on manually resolving @Dependent bean | |
248 | * in {@link #getContextualReference(Class, boolean, java.lang.annotation.Annotation...)}!</p> | |
249 | * <p><b>Attention:</b> This will also return instances of beans for which an Alternative | |
250 | * exists! The @Alternative resolving is only done via {@link BeanManager#resolve(java.util.Set)} | |
251 | * which we cannot use in this case!</p> | |
252 | * | |
253 | * @param type the type of the bean in question | |
254 | * @param optional if <code>true</code> it will return an empty list if no bean could be found or created. | |
255 | * Otherwise it will throw an {@code IllegalStateException} | |
256 | * @param <T> target type | |
257 | * @return the resolved list of Contextual Reference or an empty-list if optional is true | |
258 | */ | |
259 | /* | |
260 | public static <T> List<T> getContextualReferences(Class<T> type, boolean optional) | |
261 | { | |
262 | return getContextualReferences(type, optional, true); | |
263 | }*/ | |
264 | ||
265 | /** | |
266 | * <p>Get a list of Contextual References by type independent of the qualifier. | |
267 | * | |
268 | * Further details are available at {@link #getContextualReferences(Class, boolean)} | |
269 | * <p><b>Attention:</b> please see the notes on manually resolving @Dependent bean | |
270 | * in {@link #getContextualReference(Class, boolean, java.lang.annotation.Annotation...)}!</p> | |
271 | * <p><b>Attention:</b> This will also return instances of beans for which an Alternative | |
272 | * exists! The @Alternative resolving is only done via {@link BeanManager#resolve(java.util.Set)} | |
273 | * which we cannot use in this case!</p> | |
274 | * | |
275 | * @param type the type of the bean in question | |
276 | * @param optional if <code>true</code> it will return an empty list if no bean could be found or created. | |
277 | * Otherwise it will throw an {@code IllegalStateException} | |
278 | * @param includeDefaultScopedBeans specifies if dependent scoped beans should be included in the result | |
279 | * @param <T> target type | |
280 | * @return the resolved list of Contextual Reference or an empty-list if optional is true | |
281 | */ | |
282 | /* | |
283 | public static <T> List<T> getContextualReferences(Class<T> type, | |
284 | boolean optional, | |
285 | boolean includeDefaultScopedBeans) | |
286 | { | |
287 | BeanManager beanManager = getBeanManager(); | |
288 | ||
289 | Set<Bean<T>> beans = getBeanDefinitions(type, optional, includeDefaultScopedBeans, beanManager); | |
290 | ||
291 | List<T> result = new ArrayList<T>(beans.size()); | |
292 | ||
293 | for (Bean<?> bean : beans) | |
294 | { | |
295 | //noinspection unchecked | |
296 | result.add(getContextualReference(type, beanManager, bean)); | |
297 | } | |
298 | return result; | |
299 | }*/ | |
300 | ||
301 | /** | |
302 | * Get a set of {@link Bean} definitions by type independent of the qualifier. | |
303 | * | |
304 | * @param type the type of the bean in question | |
305 | * @param optional if <code>true</code> it will return an empty set if no bean could be found. | |
306 | * Otherwise it will throw an {@code IllegalStateException} | |
307 | * @param includeDefaultScopedBeans specifies if dependent scoped beans should be included in the result | |
308 | * @param <T> target type | |
309 | * @return the resolved set of {@link Bean} definitions or an empty-set if optional is true | |
310 | */ | |
311 | /* | |
312 | public static <T> Set<Bean<T>> getBeanDefinitions(Class<T> type, | |
313 | boolean optional, | |
314 | boolean includeDefaultScopedBeans) | |
315 | { | |
316 | BeanManager beanManager = getBeanManager(); | |
317 | | |
318 | return getBeanDefinitions(type, optional, includeDefaultScopedBeans, beanManager); | |
319 | }*/ | |
320 | /* | |
321 | private static <T> Set<Bean<T>> getBeanDefinitions(Class<T> type, | |
322 | boolean optional, | |
323 | boolean includeDefaultScopedBeans, | |
324 | BeanManager beanManager) | |
325 | { | |
326 | Set<Bean<?>> beans = beanManager.getBeans(type, new AnyLiteral()); | |
327 | ||
328 | if (beans == null || beans.isEmpty()) | |
329 | { | |
330 | if (optional) | |
331 | { | |
332 | return Collections.emptySet(); | |
333 | } | |
334 | ||
335 | throw new IllegalStateException("Could not find beans for Type=" + type); | |
336 | } | |
337 | ||
338 | if (!includeDefaultScopedBeans) | |
339 | { | |
340 | beans = filterDefaultScopedBeans(beans); | |
341 | } | |
342 | | |
343 | Set<Bean<T>> result = new HashSet<Bean<T>>(); | |
344 | | |
345 | for (Bean<?> bean : beans) | |
346 | { | |
347 | //noinspection unchecked | |
348 | result.add((Bean<T>) bean); | |
349 | } | |
350 | | |
351 | return result; | |
352 | }*/ | |
353 | ||
354 | /** | |
355 | * Allows to perform dependency injection for instances which aren't managed by CDI. | |
356 | * <p/> | |
357 | * Attention:<br/> | |
358 | * The resulting instance isn't managed by CDI; only fields annotated with @Inject get initialized. | |
359 | * | |
360 | * @param instance current instance | |
361 | * @param <T> current type | |
362 | * @return instance with injected fields (if possible - or null if the given instance is null) | |
363 | *//* | |
364 | @SuppressWarnings("unchecked") | |
365 | public static <T> T injectFields(T instance) | |
366 | { | |
367 | if (instance == null) | |
368 | { | |
369 | return null; | |
370 | } | |
371 | ||
372 | BeanManager beanManager = getBeanManager(); | |
373 | ||
374 | CreationalContext creationalContext = beanManager.createCreationalContext(null); | |
375 | ||
376 | AnnotatedType annotatedType = beanManager.createAnnotatedType(instance.getClass()); | |
377 | InjectionTarget injectionTarget = beanManager.createInjectionTarget(annotatedType); | |
378 | injectionTarget.inject(instance, creationalContext); | |
379 | return instance; | |
380 | }*/ | |
381 | ||
382 | /* | |
383 | private static Set<Bean<?>> filterDefaultScopedBeans(Set<Bean<?>> beans) | |
384 | { | |
385 | Set<Bean<?>> result = new HashSet<Bean<?>>(beans.size()); | |
386 | ||
387 | Iterator<Bean<?>> beanIterator = beans.iterator(); | |
388 | ||
389 | Bean<?> currentBean; | |
390 | while (beanIterator.hasNext()) | |
391 | { | |
392 | currentBean = beanIterator.next(); | |
393 | ||
394 | if (!Dependent.class.isAssignableFrom(currentBean.getScope())) | |
395 | { | |
396 | result.add(currentBean); | |
397 | } | |
398 | } | |
399 | return result; | |
400 | }*/ | |
401 | ||
402 | /** | |
403 | * Internal helper method to resolve the right bean and resolve the contextual reference. | |
404 | * | |
405 | * @param type the type of the bean in question | |
406 | * @param beanManager current bean-manager | |
407 | * @param beans beans in question | |
408 | * @param <T> target type | |
409 | * @return the contextual reference | |
410 | */ | |
411 | private static <T> T getContextualReference(Class<T> type, BeanManager beanManager, Set<Bean<?>> beans) | |
412 | { | |
413 | 0 | Bean<?> bean = beanManager.resolve(beans); |
414 | ||
415 | //logWarningIfDependent(bean); | |
416 | ||
417 | 0 | CreationalContext<?> creationalContext = beanManager.createCreationalContext(bean); |
418 | ||
419 | @SuppressWarnings({ "unchecked", "UnnecessaryLocalVariable" }) | |
420 | 0 | T result = (T) beanManager.getReference(bean, type, creationalContext); |
421 | 0 | return result; |
422 | } | |
423 | ||
424 | /** | |
425 | * Log a warning if the produced creational instance is of | |
426 | * Scope @Dependent as we cannot properly cleanup | |
427 | * the contextual instance afterwards. | |
428 | */ | |
429 | /* | |
430 | private static void logWarningIfDependent(Bean<?> bean) | |
431 | { | |
432 | if (LOG_DEPENDENT_WARNINGS && bean.getScope().equals(Dependent.class)) | |
433 | { | |
434 | LOG.log(Level.WARNING, "BeanProvider shall not be used to create @Dependent scoped beans. " | |
435 | + "Bean: " + bean.toString()); | |
436 | } | |
437 | }*/ | |
438 | ||
439 | /** | |
440 | * Internal method to resolve the BeanManager via the {@link BeanManagerProvider} | |
441 | * @return current bean-manager | |
442 | */ | |
443 | /* | |
444 | private static BeanManager getBeanManager() | |
445 | { | |
446 | return BeanManagerProvider.getInstance().getBeanManager(); | |
447 | }*/ | |
448 | } |