1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.flow.cdi;
20
21 import java.lang.annotation.Annotation;
22 import java.util.List;
23 import java.util.Map;
24 import javax.enterprise.context.ContextNotActiveException;
25 import javax.enterprise.context.spi.Context;
26 import javax.enterprise.context.spi.Contextual;
27 import javax.enterprise.context.spi.CreationalContext;
28 import javax.enterprise.inject.Typed;
29 import javax.enterprise.inject.spi.Bean;
30 import javax.enterprise.inject.spi.BeanManager;
31 import javax.enterprise.inject.spi.PassivationCapable;
32 import javax.faces.context.FacesContext;
33 import javax.faces.flow.Flow;
34 import javax.faces.flow.FlowHandler;
35 import javax.faces.flow.FlowScoped;
36 import org.apache.myfaces.cdi.util.BeanProvider;
37 import org.apache.myfaces.cdi.util.ContextualInstanceInfo;
38 import org.apache.myfaces.cdi.util.ContextualStorage;
39 import org.apache.myfaces.flow.FlowReference;
40 import org.apache.myfaces.flow.util.FlowUtils;
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 @Typed()
57 public class FlowScopedContextImpl implements Context
58 {
59
60
61
62 private final boolean passivatingScope;
63
64
65
66
67 private BeanManager beanManager;
68
69 private Map<Class, FlowReference> flowBeanReferences;
70
71
72
73 public FlowScopedContextImpl(BeanManager beanManager,
74 Map<Class, FlowReference> flowBeanReferences)
75 {
76 this.beanManager = beanManager;
77 this.flowBeanReferences = flowBeanReferences;
78 passivatingScope = beanManager.isPassivatingScope(getScope());
79 }
80
81
82
83
84
85
86
87 protected FlowScopeBeanHolder getFlowScopeBeanHolder()
88 {
89 return getFlowScopeBeanHolder(FacesContext.getCurrentInstance());
90 }
91
92 protected FlowScopeBeanHolder getFlowScopeBeanHolder(FacesContext facesContext)
93 {
94 FlowScopeBeanHolder flowScopeBeanHolder = (FlowScopeBeanHolder)
95 facesContext.getExternalContext().getApplicationMap().get(
96 "oam.flow.FlowScopeBeanHolder");
97 if (flowScopeBeanHolder == null)
98 {
99 flowScopeBeanHolder = BeanProvider.getContextualReference(
100 beanManager, FlowScopeBeanHolder.class, false);
101 facesContext.getExternalContext().getApplicationMap().put(
102 "oam.flow.FlowScopeBeanHolder", flowScopeBeanHolder);
103 }
104 return flowScopeBeanHolder;
105 }
106
107 public String getCurrentClientWindowFlowId(FacesContext facesContext)
108 {
109 String flowMapKey = null;
110 FlowHandler flowHandler = facesContext.getApplication().getFlowHandler();
111 Flow flow = flowHandler.getCurrentFlow(facesContext);
112 if (flow != null)
113 {
114 flowMapKey = FlowUtils.getFlowMapKey(facesContext, flow);
115 }
116 return flowMapKey;
117 }
118
119
120
121
122
123
124
125 protected ContextualStorage getContextualStorage(boolean createIfNotExist, String clientWindowFlowId)
126 {
127
128
129 if (clientWindowFlowId == null)
130 {
131 throw new ContextNotActiveException("FlowScopedContextImpl: no current active flow");
132 }
133
134 if (createIfNotExist)
135 {
136 return getFlowScopeBeanHolder().getContextualStorage(beanManager, clientWindowFlowId);
137 }
138 else
139 {
140 return getFlowScopeBeanHolder().getContextualStorageNoCreate(beanManager, clientWindowFlowId);
141 }
142 }
143
144 public Class<? extends Annotation> getScope()
145 {
146 return FlowScoped.class;
147 }
148
149 public boolean isActive()
150 {
151 return isActive(FacesContext.getCurrentInstance());
152 }
153
154 public boolean isActive(FacesContext facesContext)
155 {
156 if (facesContext == null)
157 {
158 return false;
159 }
160 Flow flow = facesContext.getApplication().
161 getFlowHandler().getCurrentFlow(facesContext);
162
163 return flow != null;
164 }
165
166
167
168
169 public boolean isPassivatingScope()
170 {
171 return passivatingScope;
172 }
173
174 @Override
175 public <T> T get(Contextual<T> bean)
176 {
177 FacesContext facesContext = FacesContext.getCurrentInstance();
178
179 checkActive(facesContext);
180
181
182 FlowReference reference = flowBeanReferences.get(((Bean)bean).getBeanClass());
183 if (reference != null)
184 {
185 String flowMapKey = FlowUtils.getFlowMapKey(facesContext, reference);
186 if (flowMapKey != null)
187 {
188 ContextualStorage storage = getContextualStorage(false, flowMapKey);
189 if (storage != null)
190 {
191 Map<Object, ContextualInstanceInfo<?>> contextMap = storage.getStorage();
192 ContextualInstanceInfo<?> contextualInstanceInfo = contextMap.get(storage.getBeanKey(bean));
193
194 if (contextualInstanceInfo != null)
195 {
196 return (T) contextualInstanceInfo.getContextualInstance();
197 }
198 }
199 }
200 else
201 {
202 throw new IllegalStateException("Flow "+ reference.getId()+
203 " cannot be found when resolving bean " +bean.toString());
204 }
205 }
206
207 List<String> activeFlowMapKeys = getFlowScopeBeanHolder().getActiveFlowMapKeys(facesContext);
208 for (String flowMapKey : activeFlowMapKeys)
209 {
210 ContextualStorage storage = getContextualStorage(false, flowMapKey);
211 if (storage == null)
212 {
213
214 continue;
215 }
216
217 Map<Object, ContextualInstanceInfo<?>> contextMap = storage.getStorage();
218 ContextualInstanceInfo<?> contextualInstanceInfo = contextMap.get(storage.getBeanKey(bean));
219 if (contextualInstanceInfo == null)
220 {
221
222 continue;
223 }
224
225 return (T) contextualInstanceInfo.getContextualInstance();
226 }
227 return null;
228 }
229
230 @Override
231 public <T> T get(Contextual<T> bean, CreationalContext<T> creationalContext)
232 {
233 FacesContext facesContext = FacesContext.getCurrentInstance();
234
235 checkActive(facesContext);
236
237 if (passivatingScope && !(bean instanceof PassivationCapable))
238 {
239 throw new IllegalStateException(bean.toString() +
240 " doesn't implement " + PassivationCapable.class.getName());
241 }
242
243 FlowReference reference = flowBeanReferences.get(((Bean)bean).getBeanClass());
244 if (reference != null)
245 {
246 String flowMapKey = FlowUtils.getFlowMapKey(facesContext, reference);
247 if (flowMapKey != null)
248 {
249 ContextualStorage storage = getContextualStorage(false, flowMapKey);
250 if (storage != null)
251 {
252 Map<Object, ContextualInstanceInfo<?>> contextMap = storage.getStorage();
253 ContextualInstanceInfo<?> contextualInstanceInfo = contextMap.get(storage.getBeanKey(bean));
254
255 if (contextualInstanceInfo != null)
256 {
257 return (T) contextualInstanceInfo.getContextualInstance();
258 }
259 }
260 }
261 else
262 {
263 throw new IllegalStateException("Flow "+ reference.getId()+
264 " cannot be found when resolving bean " + bean.toString());
265 }
266
267 FlowHandler flowHandler = facesContext.getApplication().getFlowHandler();
268
269
270
271 Flow flow = flowHandler.getFlow(facesContext,
272 reference.getDocumentId() == null ? "" : reference.getDocumentId(), reference.getId());
273 if (flow == null)
274 {
275 throw new IllegalStateException(bean.toString() + "cannot be created because flow "+ reference.getId()+
276 " is not registered");
277 }
278 if (!flowHandler.isActive(facesContext, flow.getDefiningDocumentId(), flow.getId()))
279 {
280 throw new IllegalStateException(bean.toString() + "cannot be created if flow "+ reference.getId()+
281 " is not active");
282 }
283
284 ContextualStorage storage = getContextualStorage(true, flowMapKey);
285 Map<Object, ContextualInstanceInfo<?>> contextMap = storage.getStorage();
286 ContextualInstanceInfo<?> contextualInstanceInfo = contextMap.get(storage.getBeanKey(bean));
287
288 if (contextualInstanceInfo != null)
289 {
290 @SuppressWarnings("unchecked")
291 final T instance = (T) contextualInstanceInfo.getContextualInstance();
292
293 if (instance != null)
294 {
295 return instance;
296 }
297 }
298
299 return storage.createContextualInstance(bean, creationalContext);
300 }
301
302 List<String> activeFlowMapKeys = getFlowScopeBeanHolder().getActiveFlowMapKeys(facesContext);
303 for (String flowMapKey : activeFlowMapKeys)
304 {
305 ContextualStorage storage = getContextualStorage(false, flowMapKey);
306
307 Map<Object, ContextualInstanceInfo<?>> contextMap = storage.getStorage();
308 ContextualInstanceInfo<?> contextualInstanceInfo = contextMap.get(storage.getBeanKey(bean));
309
310 if (contextualInstanceInfo != null)
311 {
312 @SuppressWarnings("unchecked")
313 final T instance = (T) contextualInstanceInfo.getContextualInstance();
314
315 if (instance != null)
316 {
317 return instance;
318 }
319 }
320
321 }
322
323 ContextualStorage storage = getContextualStorage(true, getCurrentClientWindowFlowId(facesContext));
324 Map<Object, ContextualInstanceInfo<?>> contextMap = storage.getStorage();
325 ContextualInstanceInfo<?> contextualInstanceInfo = contextMap.get(storage.getBeanKey(bean));
326
327 if (contextualInstanceInfo != null)
328 {
329 @SuppressWarnings("unchecked")
330 final T instance = (T) contextualInstanceInfo.getContextualInstance();
331
332 if (instance != null)
333 {
334 return instance;
335 }
336 }
337
338 return storage.createContextualInstance(bean, creationalContext);
339 }
340
341
342
343
344
345
346 public boolean destroy(Contextual bean)
347 {
348 FacesContext facesContext = FacesContext.getCurrentInstance();
349 List<String> activeFlowMapKeys = getFlowScopeBeanHolder().getActiveFlowMapKeys(facesContext);
350 for (String flowMapKey : activeFlowMapKeys)
351 {
352 ContextualStorage storage = getContextualStorage(false, flowMapKey);
353 if (storage == null)
354 {
355
356 continue;
357 }
358 ContextualInstanceInfo<?> contextualInstanceInfo = storage.getStorage().get(storage.getBeanKey(bean));
359
360 if (contextualInstanceInfo == null)
361 {
362
363 continue;
364 }
365
366 bean.destroy(contextualInstanceInfo.getContextualInstance(), contextualInstanceInfo.getCreationalContext());
367 return true;
368 }
369 return false;
370 }
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393 public static void destroyAllActive(ContextualStorage storage)
394 {
395 Map<Object, ContextualInstanceInfo<?>> contextMap = storage.getStorage();
396 for (Map.Entry<Object, ContextualInstanceInfo<?>> entry : contextMap.entrySet())
397 {
398 if (!FlowScopeBeanHolder.CURRENT_FLOW_SCOPE_MAP.equals(entry.getKey()))
399 {
400 Contextual bean = storage.getBean(entry.getKey());
401
402 ContextualInstanceInfo<?> contextualInstanceInfo = entry.getValue();
403 bean.destroy(contextualInstanceInfo.getContextualInstance(),
404 contextualInstanceInfo.getCreationalContext());
405 }
406 }
407 }
408
409
410
411
412
413
414 protected void checkActive(FacesContext facesContext)
415 {
416 if (!isActive(facesContext))
417 {
418 throw new ContextNotActiveException("CDI context with scope annotation @"
419 + getScope().getName() + " is not active with respect to the current thread");
420 }
421 }
422
423 }