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 @Override
103 public void onSessionDestroyed()
104 {
105 FacesContext facesContext = FacesContext.getCurrentInstance();
106 if (facesContext.getExternalContext().getSession(false) != null)
107 {
108 ExternalContext external = facesContext.getExternalContext();
109 Map<String, Object> sessionMap = external.getSessionMap();
110 String prefix = VIEW_SCOPE_PREFIX_MAP + SEPARATOR_CHAR;
111 Set<String> viewScopeIdSet = new HashSet<String>();
112 for (Map.Entry<String,Object> entry: sessionMap.entrySet())
113 {
114 if (entry.getKey() != null &&
115 entry.getKey().startsWith(prefix))
116 {
117 String viewScopeId = entry.getKey().substring(prefix.length(),
118 entry.getKey().indexOf(SEPARATOR_CHAR, prefix.length()));
119 viewScopeIdSet.add(viewScopeId);
120 }
121 }
122 if (!viewScopeIdSet.isEmpty())
123 {
124 for (String viewScopeId : viewScopeIdSet )
125 {
126 this.destroyViewScopeMap(facesContext, viewScopeId);
127 }
128 }
129 }
130 }
131
132 @Override
133 public Map<String, Object> createViewScopeMap(FacesContext facesContext, String viewScopeId)
134 {
135 String fullToken = VIEW_SCOPE_PREFIX_MAP + SEPARATOR_CHAR + viewScopeId + SEPARATOR_CHAR;
136 Map<String, Object> map = _createSubKeyMap(facesContext, fullToken);
137 return map;
138 }
139
140 @Override
141 public Map<String, Object> restoreViewScopeMap(FacesContext facesContext, String viewScopeId)
142 {
143 String fullToken = VIEW_SCOPE_PREFIX_MAP + SEPARATOR_CHAR + viewScopeId + SEPARATOR_CHAR;
144 Map<String, Object> map = _createSubKeyMap(facesContext, fullToken);
145 return map;
146 }
147
148 private Map<String, Object> _createSubKeyMap(FacesContext context, String prefix)
149 {
150 ExternalContext external = context.getExternalContext();
151 Map<String, Object> sessionMap = external.getSessionMap();
152
153 return new SubKeyMap<Object>(sessionMap, prefix);
154 }
155
156 @Override
157 public String generateViewScopeId(FacesContext facesContext)
158 {
159
160
161
162 ExternalContext externalContext = facesContext.getExternalContext();
163 Object sessionObj = externalContext.getSession(true);
164 Integer sequence = null;
165
166
167 synchronized (sessionObj)
168 {
169 Map<String, Object> map = externalContext.getSessionMap();
170 sequence = (Integer) map.get(VIEW_SCOPE_PREFIX_KEY);
171 if (sequence == null || sequence.intValue() == Integer.MAX_VALUE)
172 {
173 sequence = Integer.valueOf(1);
174 }
175 else
176 {
177 sequence = Integer.valueOf(sequence.intValue());
178 }
179 map.put(VIEW_SCOPE_PREFIX_KEY, sequence);
180 }
181 return _getNextToken()+'_'+sequence.toString();
182 }
183
184 @Override
185 public void destroyViewScopeMap(FacesContext facesContext, String viewScopeId)
186 {
187 if (facesContext.getExternalContext().getSession(false) != null)
188 {
189 String fullToken = VIEW_SCOPE_PREFIX_MAP + SEPARATOR_CHAR + viewScopeId + SEPARATOR_CHAR;
190 Map<String, Object> map = _createSubKeyMap(facesContext, fullToken);
191
192 ManagedBeanDestroyer mbDestroyer = getManagedBeanDestroyer(facesContext.getExternalContext());
193 for (Map.Entry<String,Object> entry : map.entrySet())
194 {
195 mbDestroyer.destroy(entry.getKey(), entry.getValue());
196 }
197
198 map.clear();
199 }
200 }
201
202 protected ManagedBeanDestroyer getManagedBeanDestroyer(ExternalContext externalContext)
203 {
204 if (_mbDestroyer == null)
205 {
206 RuntimeConfig runtimeConfig = RuntimeConfig.getCurrentInstance(externalContext);
207 LifecycleProvider lifecycleProvider = LifecycleProviderFactory
208 .getLifecycleProviderFactory(externalContext).getLifecycleProvider(externalContext);
209
210 _mbDestroyer = new ManagedBeanDestroyer(lifecycleProvider, runtimeConfig);
211 }
212 return _mbDestroyer;
213 }
214 }