1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.application.viewstate;
20
21 import java.io.Serializable;
22 import java.util.ArrayList;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.logging.Level;
27 import java.util.logging.Logger;
28 import javax.faces.context.FacesContext;
29 import org.apache.commons.collections.map.AbstractReferenceMap;
30 import org.apache.commons.collections.map.ReferenceMap;
31 import org.apache.myfaces.shared.util.WebConfigParamUtils;
32
33
34
35
36 class SerializedViewCollection implements Serializable
37 {
38 private static final Logger log = Logger.getLogger(SerializedViewCollection.class.getName());
39
40 private static final Object[] EMPTY_STATES = new Object[]{null, null};
41
42 private static final long serialVersionUID = -3734849062185115847L;
43 private final List<SerializedViewKey> _keys =
44 new ArrayList<SerializedViewKey>(
45 ServerSideStateCacheImpl.DEFAULT_NUMBER_OF_VIEWS_IN_SESSION);
46 private final Map<SerializedViewKey, Object> _serializedViews =
47 new HashMap<SerializedViewKey, Object>();
48
49 private final Map<SerializedViewKey, SerializedViewKey> _precedence =
50 new HashMap<SerializedViewKey, SerializedViewKey>();
51
52
53
54 private transient Map<Object, Object> _oldSerializedViews = null;
55
56 public synchronized void add(FacesContext context, Object state,
57 SerializedViewKey key, SerializedViewKey previousRestoredKey)
58 {
59 if (state == null)
60 {
61 state = EMPTY_STATES;
62 }
63 else if (state instanceof Object[] &&
64 ((Object[])state).length == 2 &&
65 ((Object[])state)[0] == null &&
66 ((Object[])state)[1] == null)
67 {
68
69
70 state = null;
71 }
72
73 Integer maxCount = getNumberOfSequentialViewsInSession(context);
74 if (maxCount != null)
75 {
76 if (previousRestoredKey != null)
77 {
78 if (!_serializedViews.isEmpty())
79 {
80 _precedence.put((SerializedViewKey) key, previousRestoredKey);
81 }
82 else
83 {
84
85
86
87
88
89 previousRestoredKey = null;
90 }
91 }
92 }
93 _serializedViews.put(key, state);
94
95 while (_keys.remove(key))
96 {
97
98 }
99 _keys.add(key);
100
101 if (previousRestoredKey != null && maxCount != null && maxCount > 0)
102 {
103 int count = 0;
104 SerializedViewKey previousKey = (SerializedViewKey) key;
105 do
106 {
107 previousKey = _precedence.get(previousKey);
108 count++;
109 }
110 while (previousKey != null && count < maxCount);
111
112 if (previousKey != null)
113 {
114 SerializedViewKey keyToRemove = (SerializedViewKey) previousKey;
115
116
117
118 do
119 {
120 while (_keys.remove(keyToRemove))
121 {
122
123 }
124
125 if (_serializedViews.containsKey(keyToRemove) &&
126 !ServerSideStateCacheImpl.CACHE_OLD_VIEWS_IN_SESSION_MODE_OFF.
127 equals( getCacheOldViewsInSessionMode(context)) )
128 {
129 getOldSerializedViewsMap().put(keyToRemove, _serializedViews.remove(keyToRemove));
130 }
131 else
132 {
133 _serializedViews.remove(keyToRemove);
134 }
135
136 keyToRemove = _precedence.remove(keyToRemove);
137 }
138 while (keyToRemove != null);
139 }
140 }
141 int views = getNumberOfViewsInSession(context);
142 while (_keys.size() > views)
143 {
144 key = _keys.remove(0);
145 if (maxCount != null && maxCount > 0)
146 {
147 SerializedViewKey keyToRemove = (SerializedViewKey) key;
148
149
150
151 do
152 {
153 keyToRemove = _precedence.remove(keyToRemove);
154 }
155 while (keyToRemove != null);
156 }
157 if (_serializedViews.containsKey(key) &&
158 !ServerSideStateCacheImpl.CACHE_OLD_VIEWS_IN_SESSION_MODE_OFF.
159 equals( getCacheOldViewsInSessionMode( context )))
160 {
161
162 getOldSerializedViewsMap().put(key, _serializedViews.remove(key));
163 }
164 else
165 {
166 _serializedViews.remove(key);
167 }
168 }
169 }
170
171 protected Integer getNumberOfSequentialViewsInSession(FacesContext context)
172 {
173 return WebConfigParamUtils.getIntegerInitParameter( context.getExternalContext(),
174 ServerSideStateCacheImpl.NUMBER_OF_SEQUENTIAL_VIEWS_IN_SESSION_PARAM);
175 }
176
177
178
179
180
181
182
183 protected int getNumberOfViewsInSession(FacesContext context)
184 {
185 String value = context.getExternalContext().getInitParameter(
186 ServerSideStateCacheImpl.NUMBER_OF_VIEWS_IN_SESSION_PARAM);
187 int views = ServerSideStateCacheImpl.DEFAULT_NUMBER_OF_VIEWS_IN_SESSION;
188 if (value != null)
189 {
190 try
191 {
192 views = Integer.parseInt(value);
193 if (views <= 0)
194 {
195 log.severe("Configured value for " + ServerSideStateCacheImpl.NUMBER_OF_VIEWS_IN_SESSION_PARAM
196 + " is not valid, must be an value > 0, using default value ("
197 + ServerSideStateCacheImpl.DEFAULT_NUMBER_OF_VIEWS_IN_SESSION);
198 views = ServerSideStateCacheImpl.DEFAULT_NUMBER_OF_VIEWS_IN_SESSION;
199 }
200 }
201 catch (Throwable e)
202 {
203 log.log( Level.SEVERE, "Error determining the value for "
204 + ServerSideStateCacheImpl.NUMBER_OF_VIEWS_IN_SESSION_PARAM
205 + ", expected an integer value > 0, using default value ("
206 + ServerSideStateCacheImpl.DEFAULT_NUMBER_OF_VIEWS_IN_SESSION + "): " + e.getMessage(), e);
207 }
208 }
209 return views;
210 }
211
212
213
214
215 @SuppressWarnings("unchecked")
216 protected Map<Object, Object> getOldSerializedViewsMap()
217 {
218 FacesContext context = FacesContext.getCurrentInstance();
219 if (_oldSerializedViews == null && context != null)
220 {
221 String cacheMode = getCacheOldViewsInSessionMode(context);
222 if ( ServerSideStateCacheImpl.CACHE_OLD_VIEWS_IN_SESSION_MODE_WEAK.equals(cacheMode))
223 {
224 _oldSerializedViews = new ReferenceMap( AbstractReferenceMap.WEAK, AbstractReferenceMap.WEAK, true);
225 }
226 else if ( ServerSideStateCacheImpl.CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT_WEAK.equals(cacheMode))
227 {
228 _oldSerializedViews = new ReferenceMap(AbstractReferenceMap.SOFT, AbstractReferenceMap.WEAK, true);
229 }
230 else if ( ServerSideStateCacheImpl.CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT.equals(cacheMode))
231 {
232 _oldSerializedViews = new ReferenceMap(AbstractReferenceMap.SOFT, AbstractReferenceMap.SOFT, true);
233 }
234 else if ( ServerSideStateCacheImpl.CACHE_OLD_VIEWS_IN_SESSION_MODE_HARD_SOFT.equals(cacheMode))
235 {
236 _oldSerializedViews = new ReferenceMap(AbstractReferenceMap.HARD, AbstractReferenceMap.SOFT);
237 }
238 }
239
240 return _oldSerializedViews;
241 }
242
243
244
245
246
247
248
249
250
251 protected String getCacheOldViewsInSessionMode(FacesContext context)
252 {
253 String value = context.getExternalContext().getInitParameter(
254 ServerSideStateCacheImpl.CACHE_OLD_VIEWS_IN_SESSION_MODE);
255 if (value == null)
256 {
257 return ServerSideStateCacheImpl.CACHE_OLD_VIEWS_IN_SESSION_MODE_OFF;
258 }
259 else if (value.equalsIgnoreCase( ServerSideStateCacheImpl.CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT))
260 {
261 return ServerSideStateCacheImpl.CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT;
262 }
263 else if (value.equalsIgnoreCase( ServerSideStateCacheImpl.CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT_WEAK))
264 {
265 return ServerSideStateCacheImpl.CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT_WEAK;
266 }
267 else if (value.equalsIgnoreCase( ServerSideStateCacheImpl.CACHE_OLD_VIEWS_IN_SESSION_MODE_WEAK))
268 {
269 return ServerSideStateCacheImpl.CACHE_OLD_VIEWS_IN_SESSION_MODE_WEAK;
270 }
271 else if (value.equalsIgnoreCase( ServerSideStateCacheImpl.CACHE_OLD_VIEWS_IN_SESSION_MODE_HARD_SOFT))
272 {
273 return ServerSideStateCacheImpl.CACHE_OLD_VIEWS_IN_SESSION_MODE_HARD_SOFT;
274 }
275 else
276 {
277 return ServerSideStateCacheImpl.CACHE_OLD_VIEWS_IN_SESSION_MODE_OFF;
278 }
279 }
280
281 public Object get(SerializedViewKey key)
282 {
283 Object value = _serializedViews.get(key);
284 if (value == null)
285 {
286 if (_serializedViews.containsKey(key))
287 {
288 return EMPTY_STATES;
289 }
290 Map<Object,Object> oldSerializedViewMap = getOldSerializedViewsMap();
291 if (oldSerializedViewMap != null)
292 {
293 value = oldSerializedViewMap.get(key);
294 if (value == null && oldSerializedViewMap.containsKey(key) )
295 {
296 return EMPTY_STATES;
297 }
298 }
299 }
300 else if (value instanceof Object[] &&
301 ((Object[])value).length == 2 &&
302 ((Object[])value)[0] == null &&
303 ((Object[])value)[1] == null)
304 {
305
306 return null;
307 }
308 return value;
309 }
310 }