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 package org.jcr_blog.commons.jsf2cdi.scope;
40
41 import java.lang.annotation.Annotation;
42 import java.util.Map;
43 import java.util.Map.Entry;
44 import java.util.concurrent.ConcurrentHashMap;
45 import javax.enterprise.context.ContextNotActiveException;
46 import javax.enterprise.context.spi.Context;
47 import javax.enterprise.context.spi.Contextual;
48 import javax.enterprise.context.spi.CreationalContext;
49 import javax.faces.component.UIViewRoot;
50 import javax.faces.context.FacesContext;
51 import javax.faces.event.PreDestroyViewMapEvent;
52 import javax.faces.event.SystemEvent;
53 import javax.faces.event.SystemEventListener;
54
55
56
57
58
59
60
61
62
63
64
65 public class ViewContext implements Context, SystemEventListener {
66
67 private final static String COMPONENT_MAP_NAME = "org.jboss.seam.faces.viewscope.componentInstanceMap";
68 private final static String CREATIONAL_MAP_NAME = "org.jboss.seam.faces.viewscope.creationalInstanceMap";
69
70 private boolean isJsfSubscribed = false;
71
72 @SuppressWarnings("unchecked")
73 @Override
74 public <T> T get(final Contextual<T> component) {
75 assertActive();
76
77 if (!isJsfSubscribed) {
78 FacesContext.getCurrentInstance().getApplication().subscribeToEvent(PreDestroyViewMapEvent.class, this);
79 isJsfSubscribed = true;
80 }
81
82 T instance = (T) getComponentInstanceMap().get(component);
83
84 return instance;
85 }
86
87 @SuppressWarnings("unchecked")
88 @Override
89 public <T> T get(final Contextual<T> component, final CreationalContext<T> creationalContext) {
90 assertActive();
91
92 T instance = get(component);
93 if (instance == null && creationalContext != null) {
94 Map<Contextual<?>, Object> componentInstanceMap = getComponentInstanceMap();
95 Map<Contextual<?>, CreationalContext<?>> creationalContextMap = getCreationalInstanceMap();
96
97 synchronized (componentInstanceMap) {
98 instance = (T) componentInstanceMap.get(component);
99 if (instance == null) {
100 instance = component.create(creationalContext);
101 if (instance != null) {
102 componentInstanceMap.put(component, instance);
103 creationalContextMap.put(component, creationalContext);
104 }
105 }
106 }
107 }
108
109 return instance;
110 }
111
112
113
114
115
116 private Map<String, Object> getViewMap() {
117 UIViewRoot viewRoot = getUIViewRoot();
118 if (viewRoot == null) {
119 return null;
120 }
121 return viewRoot.getViewMap();
122 }
123
124 private UIViewRoot getUIViewRoot() {
125 FacesContext ctx = FacesContext.getCurrentInstance();
126 if (ctx == null) {
127 return null;
128 }
129 return ctx.getViewRoot();
130 }
131
132
133
134
135
136
137
138
139 @Override
140 public boolean isActive() {
141 return this.getUIViewRoot() != null;
142 }
143
144
145
146
147
148
149
150
151 private void assertActive() {
152 if (!isActive()) {
153 throw new ContextNotActiveException("Context @ViewScoped is not active.");
154 }
155 }
156
157 private Map<Contextual<?>, Object> getComponentInstanceMap() {
158 Map<String, Object> viewMap = getViewMap();
159 Map<Contextual<?>, Object> map = (ConcurrentHashMap<Contextual<?>, Object>) viewMap.get(COMPONENT_MAP_NAME);
160
161 if (map == null) {
162 map = new ConcurrentHashMap<Contextual<?>, Object>();
163 viewMap.put(COMPONENT_MAP_NAME, map);
164 }
165
166 return map;
167 }
168
169 private Map<Contextual<?>, CreationalContext<?>> getCreationalInstanceMap() {
170 Map<String, Object> viewMap = getViewMap();
171 Map<Contextual<?>, CreationalContext<?>> map = (Map<Contextual<?>, CreationalContext<?>>) viewMap.get(CREATIONAL_MAP_NAME);
172
173 if (map == null) {
174 map = new ConcurrentHashMap<Contextual<?>, CreationalContext<?>>();
175 viewMap.put(CREATIONAL_MAP_NAME, map);
176 }
177
178 return map;
179 }
180
181 @Override
182 public Class<? extends Annotation> getScope() {
183 return ViewScoped.class;
184 }
185
186
187
188
189 @Override
190 public boolean isListenerForSource(final Object source) {
191 if (source instanceof UIViewRoot) {
192 return true;
193 }
194
195 return false;
196 }
197
198
199
200
201
202
203
204
205
206 @SuppressWarnings("unchecked")
207 @Override
208 public void processEvent(final SystemEvent event) {
209 if (event instanceof PreDestroyViewMapEvent) {
210 Map<Contextual<?>, Object> componentInstanceMap = getComponentInstanceMap();
211 Map<Contextual<?>, CreationalContext<?>> creationalContextMap = getCreationalInstanceMap();
212
213 if (componentInstanceMap != null) {
214 for (Entry<Contextual<?>, Object> componentEntry : componentInstanceMap.entrySet()) {
215
216
217
218
219 Contextual contextual = componentEntry.getKey();
220 Object instance = componentEntry.getValue();
221 CreationalContext creational = creationalContextMap.get(contextual);
222
223 contextual.destroy(instance, creational);
224 }
225 }
226 }
227 }
228 }