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