1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.view.impl;
20
21 import java.math.BigInteger;
22 import java.security.NoSuchAlgorithmException;
23 import java.security.SecureRandom;
24 import java.util.HashSet;
25 import java.util.Map;
26 import java.util.Set;
27 import java.util.concurrent.atomic.AtomicLong;
28 import javax.faces.context.ExternalContext;
29 import javax.faces.context.FacesContext;
30 import org.apache.myfaces.config.ManagedBeanDestroyer;
31 import org.apache.myfaces.config.RuntimeConfig;
32 import org.apache.myfaces.config.annotation.LifecycleProvider;
33 import org.apache.myfaces.config.annotation.LifecycleProviderFactory;
34 import org.apache.myfaces.shared.util.SubKeyMap;
35 import org.apache.myfaces.spi.ViewScopeProvider;
36
37
38
39
40
41
42
43 public class DefaultViewScopeHandler extends ViewScopeProvider
44 {
45 private static final String VIEW_SCOPE_PREFIX = "oam.view.SCOPE";
46
47 private static final String VIEW_SCOPE_PREFIX_KEY = VIEW_SCOPE_PREFIX+".KEY";
48
49 private static final String VIEW_SCOPE_PREFIX_MAP = VIEW_SCOPE_PREFIX+".MAP";
50
51 static final char SEPARATOR_CHAR = '.';
52
53 private final AtomicLong _count;
54
55 private ManagedBeanDestroyer _mbDestroyer;
56
57 public DefaultViewScopeHandler()
58 {
59 _count = new AtomicLong(_getSeed());
60 }
61
62
63
64
65 private static long _getSeed()
66 {
67 SecureRandom rng;
68 try
69 {
70
71 rng = SecureRandom.getInstance("SHA1PRNG");
72 }
73 catch (NoSuchAlgorithmException e)
74 {
75
76
77 rng = new SecureRandom();
78 }
79
80
81 byte[] randomBytes = new byte[6];
82 rng.nextBytes(randomBytes);
83
84
85 return new BigInteger(randomBytes).longValue();
86 }
87
88
89
90
91
92
93 private String _getNextToken()
94 {
95
96 long nextToken = _count.incrementAndGet();
97
98
99 return Long.toString(nextToken, 36);
100 }
101
102 public void onSessionDestroyed()
103 {
104 FacesContext facesContext = FacesContext.getCurrentInstance();
105 if (facesContext.getExternalContext().getSession(false) != null)
106 {
107 ExternalContext external = facesContext.getExternalContext();
108 Map<String, Object> sessionMap = external.getSessionMap();
109 String prefix = VIEW_SCOPE_PREFIX_MAP + SEPARATOR_CHAR;
110 Set<String> viewScopeIdSet = new HashSet<String>();
111 for (Map.Entry<String,Object> entry: sessionMap.entrySet())
112 {
113 if (entry.getKey() != null &&
114 entry.getKey().startsWith(prefix))
115 {
116 String viewScopeId = entry.getKey().substring(prefix.length(),
117 entry.getKey().indexOf(SEPARATOR_CHAR, prefix.length()));
118 viewScopeIdSet.add(viewScopeId);
119 }
120 }
121 if (!viewScopeIdSet.isEmpty())
122 {
123 for (String viewScopeId : viewScopeIdSet )
124 {
125 this.destroyViewScopeMap(facesContext, viewScopeId);
126 }
127 }
128 }
129 }
130
131 public Map<String, Object> createViewScopeMap(FacesContext facesContext, String viewScopeId)
132 {
133 String fullToken = VIEW_SCOPE_PREFIX_MAP + SEPARATOR_CHAR + viewScopeId + SEPARATOR_CHAR;
134 Map<String, Object> map = _createSubKeyMap(facesContext, fullToken);
135 return map;
136 }
137
138 public Map<String, Object> restoreViewScopeMap(FacesContext facesContext, String viewScopeId)
139 {
140 String fullToken = VIEW_SCOPE_PREFIX_MAP + SEPARATOR_CHAR + viewScopeId + SEPARATOR_CHAR;
141 Map<String, Object> map = _createSubKeyMap(facesContext, fullToken);
142 return map;
143 }
144
145 private Map<String, Object> _createSubKeyMap(FacesContext context, String prefix)
146 {
147 ExternalContext external = context.getExternalContext();
148 Map<String, Object> sessionMap = external.getSessionMap();
149
150 return new SubKeyMap<Object>(sessionMap, prefix);
151 }
152
153 public String generateViewScopeId(FacesContext facesContext)
154 {
155
156
157
158 ExternalContext externalContext = facesContext.getExternalContext();
159 Object sessionObj = externalContext.getSession(true);
160 Integer sequence = null;
161
162
163 synchronized (sessionObj)
164 {
165 Map<String, Object> map = externalContext.getSessionMap();
166 sequence = (Integer) map.get(VIEW_SCOPE_PREFIX_KEY);
167 if (sequence == null || sequence.intValue() == Integer.MAX_VALUE)
168 {
169 sequence = Integer.valueOf(1);
170 }
171 else
172 {
173 sequence = Integer.valueOf(sequence.intValue());
174 }
175 map.put(VIEW_SCOPE_PREFIX_KEY, sequence);
176 }
177 return _getNextToken()+'_'+sequence.toString();
178 }
179
180 @Override
181 public void destroyViewScopeMap(FacesContext facesContext, String viewScopeId)
182 {
183 if (facesContext.getExternalContext().getSession(false) != null)
184 {
185 String fullToken = VIEW_SCOPE_PREFIX_MAP + SEPARATOR_CHAR + viewScopeId + SEPARATOR_CHAR;
186 Map<String, Object> map = _createSubKeyMap(facesContext, fullToken);
187
188 ManagedBeanDestroyer mbDestroyer = getManagedBeanDestroyer(facesContext.getExternalContext());
189 for (Map.Entry<String,Object> entry : map.entrySet())
190 {
191 mbDestroyer.destroy(entry.getKey(), entry.getValue());
192 }
193
194 map.clear();
195 }
196 }
197
198 protected ManagedBeanDestroyer getManagedBeanDestroyer(ExternalContext externalContext)
199 {
200 if (_mbDestroyer == null)
201 {
202 RuntimeConfig runtimeConfig = RuntimeConfig.getCurrentInstance(externalContext);
203 LifecycleProvider lifecycleProvider = LifecycleProviderFactory
204 .getLifecycleProviderFactory(externalContext).getLifecycleProvider(externalContext);
205
206 _mbDestroyer = new ManagedBeanDestroyer(lifecycleProvider, runtimeConfig);
207 }
208 return _mbDestroyer;
209 }
210 }