1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.renderkit;
20
21 import java.io.ByteArrayInputStream;
22 import java.io.ByteArrayOutputStream;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.ObjectInputStream;
26 import java.io.ObjectOutputStream;
27 import java.io.OutputStream;
28 import java.io.Serializable;
29 import java.security.AccessController;
30 import java.security.PrivilegedActionException;
31 import java.security.PrivilegedExceptionAction;
32 import java.util.ArrayList;
33 import java.util.HashMap;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.logging.Level;
37 import java.util.logging.Logger;
38 import java.util.zip.GZIPInputStream;
39 import java.util.zip.GZIPOutputStream;
40
41 import javax.faces.context.ExternalContext;
42 import javax.faces.context.FacesContext;
43
44 import org.apache.commons.collections.map.AbstractReferenceMap;
45 import org.apache.commons.collections.map.ReferenceMap;
46 import org.apache.myfaces.application.StateCache;
47 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
48 import org.apache.myfaces.shared.renderkit.RendererUtils;
49 import org.apache.myfaces.shared.util.MyFacesObjectInputStream;
50 import org.apache.myfaces.shared.util.WebConfigParamUtils;
51
52 class ServerSideStateCacheImpl extends StateCache<Object, Object>
53 {
54 private static final Logger log = Logger.getLogger(ServerSideStateCacheImpl.class.getName());
55
56 private static final String SERIALIZED_VIEW_SESSION_ATTR=
57 ServerSideStateCacheImpl.class.getName() + ".SERIALIZED_VIEW";
58
59 private static final String RESTORED_SERIALIZED_VIEW_REQUEST_ATTR =
60 ServerSideStateCacheImpl.class.getName() + ".RESTORED_SERIALIZED_VIEW";
61
62 private static final String RESTORED_VIEW_KEY_REQUEST_ATTR =
63 ServerSideStateCacheImpl.class.getName() + ".RESTORED_VIEW_KEY";
64
65
66
67
68
69
70
71
72 @JSFWebConfigParam(defaultValue="20",since="1.1", classType="java.lang.Integer", group="state", tags="performance")
73 private static final String NUMBER_OF_VIEWS_IN_SESSION_PARAM = "org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION";
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88 @JSFWebConfigParam(since="2.0.6", classType="java.lang.Integer", group="state", tags="performance")
89 private static final String NUMBER_OF_SEQUENTIAL_VIEWS_IN_SESSION_PARAM
90 = "org.apache.myfaces.NUMBER_OF_SEQUENTIAL_VIEWS_IN_SESSION";
91
92
93
94
95 private static final int DEFAULT_NUMBER_OF_VIEWS_IN_SESSION = 20;
96
97
98
99
100
101
102
103
104
105 @JSFWebConfigParam(defaultValue="true",since="1.1", expectedValues="true,false", group="state", tags="performance")
106 private static final String SERIALIZE_STATE_IN_SESSION_PARAM = "org.apache.myfaces.SERIALIZE_STATE_IN_SESSION";
107
108
109
110
111
112
113
114
115
116 @JSFWebConfigParam(defaultValue="true",since="1.1", expectedValues="true,false", group="state", tags="performance")
117 private static final String COMPRESS_SERVER_STATE_PARAM = "org.apache.myfaces.COMPRESS_STATE_IN_SESSION";
118
119
120
121
122 private static final boolean DEFAULT_COMPRESS_SERVER_STATE_PARAM = true;
123
124
125
126
127 private static final boolean DEFAULT_SERIALIZE_STATE_IN_SESSION = true;
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152 @JSFWebConfigParam(defaultValue="off", expectedValues="off, no, hard-soft, soft, soft-weak, weak",
153 since="1.2.5", group="state", tags="performance")
154 private static final String CACHE_OLD_VIEWS_IN_SESSION_MODE = "org.apache.myfaces.CACHE_OLD_VIEWS_IN_SESSION_MODE";
155
156
157
158
159
160
161 private static final String CACHE_OLD_VIEWS_IN_SESSION_MODE_HARD_SOFT = "hard-soft";
162
163 private static final String CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT = "soft";
164
165 private static final String CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT_WEAK = "soft-weak";
166
167 private static final String CACHE_OLD_VIEWS_IN_SESSION_MODE_WEAK = "weak";
168
169 private static final String CACHE_OLD_VIEWS_IN_SESSION_MODE_OFF = "off";
170
171
172
173
174
175
176
177
178
179 @JSFWebConfigParam(since="2.0.6", defaultValue="false", expectedValues="true, false", group="state")
180 private static final String USE_FLASH_SCOPE_PURGE_VIEWS_IN_SESSION
181 = "org.apache.myfaces.USE_FLASH_SCOPE_PURGE_VIEWS_IN_SESSION";
182
183 private static final int UNCOMPRESSED_FLAG = 0;
184 private static final int COMPRESSED_FLAG = 1;
185
186 private static final int JSF_SEQUENCE_INDEX = 0;
187
188 private Boolean _useFlashScopePurgeViewsInSession = null;
189
190 private Integer _numberOfSequentialViewsInSession = null;
191 private boolean _numberOfSequentialViewsInSessionSet = false;
192
193
194
195 protected Integer getServerStateId(Object[] state)
196 {
197 if (state != null)
198 {
199 Object serverStateId = state[JSF_SEQUENCE_INDEX];
200 if (serverStateId != null)
201 {
202 return Integer.valueOf((String) serverStateId, Character.MAX_RADIX);
203 }
204 }
205 return null;
206 }
207
208 protected void saveSerializedViewInServletSession(FacesContext context,
209 Object serializedView)
210 {
211 Map<String, Object> sessionMap = context.getExternalContext().getSessionMap();
212 SerializedViewCollection viewCollection = (SerializedViewCollection) sessionMap
213 .get(SERIALIZED_VIEW_SESSION_ATTR);
214 if (viewCollection == null)
215 {
216 viewCollection = new SerializedViewCollection();
217 sessionMap.put(SERIALIZED_VIEW_SESSION_ATTR, viewCollection);
218 }
219
220 Map<Object,Object> attributeMap = context.getAttributes();
221
222 SerializedViewKey key = null;
223 if (getNumberOfSequentialViewsInSession(context.getExternalContext()) != null &&
224 getNumberOfSequentialViewsInSession(context.getExternalContext()) > 0)
225 {
226 key = (SerializedViewKey) attributeMap.get(RESTORED_VIEW_KEY_REQUEST_ATTR);
227
228 if (key == null )
229 {
230 if (isUseFlashScopePurgeViewsInSession(context.getExternalContext()) &&
231 Boolean.TRUE.equals(context.getExternalContext().getRequestMap()
232 .get("oam.Flash.REDIRECT.PREVIOUSREQUEST")))
233 {
234 key = (SerializedViewKey)
235 context.getExternalContext().getFlash().get(RESTORED_VIEW_KEY_REQUEST_ATTR);
236 }
237 }
238 }
239
240 viewCollection.add(context, serializeView(context, serializedView), getNextViewSequence(context), key);
241
242
243
244
245
246
247
248
249
250
251 sessionMap.put(SERIALIZED_VIEW_SESSION_ATTR, viewCollection);
252 }
253
254 protected Object getSerializedViewFromServletSession(FacesContext context, String viewId, Integer sequence)
255 {
256 ExternalContext externalContext = context.getExternalContext();
257 Map<Object, Object> attributeMap = context.getAttributes();
258 Object serializedView = null;
259 if (attributeMap.containsKey(RESTORED_SERIALIZED_VIEW_REQUEST_ATTR))
260 {
261 serializedView = attributeMap.get(RESTORED_SERIALIZED_VIEW_REQUEST_ATTR);
262 }
263 else
264 {
265 SerializedViewCollection viewCollection = (SerializedViewCollection) externalContext
266 .getSessionMap().get(SERIALIZED_VIEW_SESSION_ATTR);
267 if (viewCollection != null)
268 {
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284 if (sequence != null)
285 {
286 Object state = viewCollection.get(sequence, viewId);
287 if (state != null)
288 {
289 serializedView = deserializeView(state);
290 }
291 }
292 }
293 attributeMap.put(RESTORED_SERIALIZED_VIEW_REQUEST_ATTR, serializedView);
294
295 if (getNumberOfSequentialViewsInSession(externalContext) != null &&
296 getNumberOfSequentialViewsInSession(externalContext) > 0)
297 {
298 SerializedViewKey key = new SerializedViewKey(viewId, sequence);
299 attributeMap.put(RESTORED_VIEW_KEY_REQUEST_ATTR, key);
300
301 if (isUseFlashScopePurgeViewsInSession(externalContext))
302 {
303 externalContext.getFlash().put(RESTORED_VIEW_KEY_REQUEST_ATTR, key);
304 externalContext.getFlash().keep(RESTORED_VIEW_KEY_REQUEST_ATTR);
305 }
306 }
307
308 nextViewSequence(context);
309 }
310 return serializedView;
311 }
312
313 public int getNextViewSequence(FacesContext context)
314 {
315 if (!context.getAttributes().containsKey(RendererUtils.SEQUENCE_PARAM))
316 {
317 nextViewSequence(context);
318 }
319
320 Integer sequence = (Integer) context.getAttributes().get(RendererUtils.SEQUENCE_PARAM);
321 return sequence.intValue();
322 }
323
324 public void nextViewSequence(FacesContext facescontext)
325 {
326 ExternalContext externalContext = facescontext.getExternalContext();
327 Object sessionObj = externalContext.getSession(true);
328 Integer sequence = null;
329 synchronized(sessionObj)
330
331 {
332 Map<String, Object> map = externalContext.getSessionMap();
333 sequence = (Integer) map.get(RendererUtils.SEQUENCE_PARAM);
334 if(sequence == null || sequence.intValue() == Integer.MAX_VALUE)
335 {
336 sequence = Integer.valueOf(1);
337 }
338 else
339 {
340 sequence = Integer.valueOf(sequence.intValue() + 1);
341 }
342 map.put(RendererUtils.SEQUENCE_PARAM, sequence);
343 }
344 facescontext.getAttributes().put(RendererUtils.SEQUENCE_PARAM, sequence);
345 }
346
347 protected Object serializeView(FacesContext context, Object serializedView)
348 {
349 if (log.isLoggable(Level.FINEST))
350 {
351 log.finest("Entering serializeView");
352 }
353
354 if(isSerializeStateInSession(context))
355 {
356 if (log.isLoggable(Level.FINEST))
357 {
358 log.finest("Processing serializeView - serialize state in session");
359 }
360
361 ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
362 try
363 {
364 OutputStream os = baos;
365 if(isCompressStateInSession(context))
366 {
367 if (log.isLoggable(Level.FINEST))
368 {
369 log.finest("Processing serializeView - serialize compressed");
370 }
371
372 os.write(COMPRESSED_FLAG);
373 os = new GZIPOutputStream(os, 1024);
374 }
375 else
376 {
377 if (log.isLoggable(Level.FINEST))
378 {
379 log.finest("Processing serializeView - serialize uncompressed");
380 }
381
382 os.write(UNCOMPRESSED_FLAG);
383 }
384
385
386
387 ObjectOutputStream out = new ObjectOutputStream(os);
388
389 out.writeObject(serializedView);
390
391
392 out.close();
393 baos.close();
394
395 if (log.isLoggable(Level.FINEST))
396 {
397 log.finest("Exiting serializeView - serialized. Bytes : " + baos.size());
398 }
399 return baos.toByteArray();
400 }
401 catch (IOException e)
402 {
403 log.log(Level.SEVERE, "Exiting serializeView - Could not serialize state: " + e.getMessage(), e);
404 return null;
405 }
406 }
407
408
409 if (log.isLoggable(Level.FINEST))
410 {
411 log.finest("Exiting serializeView - do not serialize state in session.");
412 }
413
414 return serializedView;
415
416 }
417
418
419
420
421
422
423
424 protected boolean isSerializeStateInSession(FacesContext context)
425 {
426 String value = context.getExternalContext().getInitParameter(
427 SERIALIZE_STATE_IN_SESSION_PARAM);
428 boolean serialize = DEFAULT_SERIALIZE_STATE_IN_SESSION;
429 if (value != null)
430 {
431 serialize = Boolean.valueOf(value);
432 }
433 return serialize;
434 }
435
436
437
438
439
440
441
442 protected boolean isCompressStateInSession(FacesContext context)
443 {
444 String value = context.getExternalContext().getInitParameter(
445 COMPRESS_SERVER_STATE_PARAM);
446 boolean compress = DEFAULT_COMPRESS_SERVER_STATE_PARAM;
447 if (value != null)
448 {
449 compress = Boolean.valueOf(value);
450 }
451 return compress;
452 }
453
454 protected Object deserializeView(Object state)
455 {
456 if (log.isLoggable(Level.FINEST))
457 {
458 log.finest("Entering deserializeView");
459 }
460
461 if(state instanceof byte[])
462 {
463 if (log.isLoggable(Level.FINEST))
464 {
465 log.finest("Processing deserializeView - deserializing serialized state. Bytes : "
466 + ((byte[]) state).length);
467 }
468
469 try
470 {
471 ByteArrayInputStream bais = new ByteArrayInputStream((byte[]) state);
472 InputStream is = bais;
473 if(is.read() == COMPRESSED_FLAG)
474 {
475 is = new GZIPInputStream(is);
476 }
477 ObjectInputStream ois = null;
478 try
479 {
480 final ObjectInputStream in = new MyFacesObjectInputStream(is);
481 ois = in;
482 Object object = null;
483 if (System.getSecurityManager() != null)
484 {
485 object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>()
486 {
487 public Object run() throws PrivilegedActionException, IOException, ClassNotFoundException
488 {
489
490 return in.readObject();
491 }
492 });
493 }
494 else
495 {
496
497 object = in.readObject();
498 }
499 return object;
500 }
501 finally
502 {
503 if (ois != null)
504 {
505 ois.close();
506 ois = null;
507 }
508 }
509 }
510 catch (PrivilegedActionException e)
511 {
512 log.log(Level.SEVERE, "Exiting deserializeView - Could not deserialize state: " + e.getMessage(), e);
513 return null;
514 }
515 catch (IOException e)
516 {
517 log.log(Level.SEVERE, "Exiting deserializeView - Could not deserialize state: " + e.getMessage(), e);
518 return null;
519 }
520 catch (ClassNotFoundException e)
521 {
522 log.log(Level.SEVERE, "Exiting deserializeView - Could not deserialize state: " + e.getMessage(), e);
523 return null;
524 }
525 }
526 else if (state instanceof Object[])
527 {
528 if (log.isLoggable(Level.FINEST))
529 {
530 log.finest("Exiting deserializeView - state not serialized.");
531 }
532
533 return state;
534 }
535 else if(state == null)
536 {
537 log.severe("Exiting deserializeView - this method should not be called with a null-state.");
538 return null;
539 }
540 else
541 {
542 log.severe("Exiting deserializeView - this method should not be called with a state of type : "
543 + state.getClass());
544 return null;
545 }
546 }
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566 protected static class SerializedViewCollection implements Serializable
567 {
568 private static final long serialVersionUID = -3734849062185115847L;
569
570 private final List<SerializedViewKey> _keys
571 = new ArrayList<SerializedViewKey>(DEFAULT_NUMBER_OF_VIEWS_IN_SESSION);
572 private final Map<SerializedViewKey, Object> _serializedViews = new HashMap<SerializedViewKey, Object>();
573
574 private final Map<SerializedViewKey, SerializedViewKey> _precedence =
575 new HashMap<SerializedViewKey, SerializedViewKey>();
576
577
578
579 private transient Map<Object, Object> _oldSerializedViews = null;
580
581 public synchronized void add(FacesContext context, Object state, Integer nextSequence,
582 SerializedViewKey previousRestoredKey)
583 {
584 SerializedViewKey key = new SerializedViewKey(context.getViewRoot().getViewId(), nextSequence);
585 _serializedViews.put(key, state);
586
587 Integer maxCount = getNumberOfSequentialViewsInSession(context);
588 if (maxCount != null)
589 {
590 if (previousRestoredKey != null)
591 {
592 _precedence.put((SerializedViewKey) key, previousRestoredKey);
593 }
594 }
595
596 while (_keys.remove(key))
597 {
598
599 }
600 _keys.add(key);
601
602 if (previousRestoredKey != null && maxCount != null && maxCount > 0)
603 {
604 int count = 0;
605 SerializedViewKey previousKey = (SerializedViewKey) key;
606 do
607 {
608 previousKey = _precedence.get(previousKey);
609 count++;
610 } while (previousKey != null && count < maxCount);
611
612 if (previousKey != null)
613 {
614 SerializedViewKey keyToRemove = (SerializedViewKey) previousKey;
615
616
617
618 do
619 {
620 while (_keys.remove(keyToRemove))
621 {
622
623 }
624
625 Object oldView = _serializedViews.remove(keyToRemove);
626 if (oldView != null &&
627 !CACHE_OLD_VIEWS_IN_SESSION_MODE_OFF.equals(getCacheOldViewsInSessionMode(context)))
628 {
629 getOldSerializedViewsMap().put(keyToRemove, oldView);
630 }
631
632 keyToRemove = _precedence.remove(keyToRemove);
633 } while(keyToRemove != null);
634 }
635 }
636
637 int views = getNumberOfViewsInSession(context);
638 while (_keys.size() > views)
639 {
640 key = _keys.remove(0);
641
642 if (maxCount != null && maxCount > 0)
643 {
644 SerializedViewKey keyToRemove = (SerializedViewKey) key;
645
646
647
648 do
649 {
650 keyToRemove = _precedence.remove(keyToRemove);
651 } while (keyToRemove != null);
652 }
653
654 Object oldView = _serializedViews.remove(key);
655 if (oldView != null &&
656 !CACHE_OLD_VIEWS_IN_SESSION_MODE_OFF.equals(getCacheOldViewsInSessionMode(context)))
657 {
658 getOldSerializedViewsMap().put(key, oldView);
659 }
660 }
661 }
662
663 protected Integer getNumberOfSequentialViewsInSession(FacesContext context)
664 {
665 return WebConfigParamUtils.getIntegerInitParameter(context.getExternalContext(),
666 NUMBER_OF_SEQUENTIAL_VIEWS_IN_SESSION_PARAM);
667 }
668
669
670
671
672
673
674
675 protected int getNumberOfViewsInSession(FacesContext context)
676 {
677 String value = context.getExternalContext().getInitParameter(
678 NUMBER_OF_VIEWS_IN_SESSION_PARAM);
679 int views = DEFAULT_NUMBER_OF_VIEWS_IN_SESSION;
680 if (value != null)
681 {
682 try
683 {
684 views = Integer.parseInt(value);
685 if (views <= 0)
686 {
687 log.severe("Configured value for " + NUMBER_OF_VIEWS_IN_SESSION_PARAM
688 + " is not valid, must be an value > 0, using default value ("
689 + DEFAULT_NUMBER_OF_VIEWS_IN_SESSION);
690 views = DEFAULT_NUMBER_OF_VIEWS_IN_SESSION;
691 }
692 }
693 catch (Throwable e)
694 {
695 log.log(Level.SEVERE, "Error determining the value for " + NUMBER_OF_VIEWS_IN_SESSION_PARAM
696 + ", expected an integer value > 0, using default value ("
697 + DEFAULT_NUMBER_OF_VIEWS_IN_SESSION + "): " + e.getMessage(), e);
698 }
699 }
700 return views;
701 }
702
703
704
705
706 @SuppressWarnings("unchecked")
707 protected Map<Object, Object> getOldSerializedViewsMap()
708 {
709 FacesContext context = FacesContext.getCurrentInstance();
710 if (_oldSerializedViews == null && context != null)
711 {
712 String cacheMode = getCacheOldViewsInSessionMode(context);
713 if (CACHE_OLD_VIEWS_IN_SESSION_MODE_WEAK.equals(cacheMode))
714 {
715 _oldSerializedViews = new ReferenceMap(AbstractReferenceMap.WEAK, AbstractReferenceMap.WEAK, true);
716 }
717 else if (CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT_WEAK.equals(cacheMode))
718 {
719 _oldSerializedViews = new ReferenceMap(AbstractReferenceMap.SOFT, AbstractReferenceMap.WEAK, true);
720 }
721 else if (CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT.equals(cacheMode))
722 {
723 _oldSerializedViews = new ReferenceMap(AbstractReferenceMap.SOFT, AbstractReferenceMap.SOFT, true);
724 }
725 else if (CACHE_OLD_VIEWS_IN_SESSION_MODE_HARD_SOFT.equals(cacheMode))
726 {
727 _oldSerializedViews = new ReferenceMap(AbstractReferenceMap.HARD, AbstractReferenceMap.SOFT);
728 }
729 }
730
731 return _oldSerializedViews;
732 }
733
734
735
736
737
738
739
740
741
742 protected String getCacheOldViewsInSessionMode(FacesContext context)
743 {
744 String value = context.getExternalContext().getInitParameter(
745 CACHE_OLD_VIEWS_IN_SESSION_MODE);
746 if (value == null)
747 {
748 return CACHE_OLD_VIEWS_IN_SESSION_MODE_OFF;
749 }
750 else if (value.equalsIgnoreCase(CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT))
751 {
752 return CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT;
753 }
754 else if (value.equalsIgnoreCase(CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT_WEAK))
755 {
756 return CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT_WEAK;
757 }
758 else if (value.equalsIgnoreCase(CACHE_OLD_VIEWS_IN_SESSION_MODE_WEAK))
759 {
760 return CACHE_OLD_VIEWS_IN_SESSION_MODE_WEAK;
761 }
762 else if (value.equalsIgnoreCase(CACHE_OLD_VIEWS_IN_SESSION_MODE_HARD_SOFT))
763 {
764 return CACHE_OLD_VIEWS_IN_SESSION_MODE_HARD_SOFT;
765 }
766 else
767 {
768 return CACHE_OLD_VIEWS_IN_SESSION_MODE_OFF;
769 }
770 }
771
772 public Object get(Integer sequence, String viewId)
773 {
774 Object key = new SerializedViewKey(viewId, sequence);
775 Object value = _serializedViews.get(key);
776 if (value == null)
777 {
778 Map<Object,Object> oldSerializedViewMap = getOldSerializedViewsMap();
779 if (oldSerializedViewMap != null)
780 {
781 value = oldSerializedViewMap.get(key);
782 }
783 }
784 return value;
785 }
786 }
787
788 protected static class SerializedViewKey implements Serializable
789 {
790 private static final long serialVersionUID = -1170697124386063642L;
791
792 private final String _viewId;
793 private final Integer _sequenceId;
794
795 public SerializedViewKey(String viewId, Integer sequence)
796 {
797 _sequenceId = sequence;
798 _viewId = viewId;
799 }
800
801
802
803
804
805
806
807
808 @Override
809 public int hashCode()
810 {
811 final int prime = 31;
812 int result = 1;
813 result = prime * result + ((_sequenceId == null) ? 0 : _sequenceId.hashCode());
814 result = prime * result + ((_viewId == null) ? 0 : _viewId.hashCode());
815 return result;
816 }
817
818 @Override
819 public boolean equals(Object obj)
820 {
821 if (this == obj)
822 {
823 return true;
824 }
825 if (obj == null)
826 {
827 return false;
828 }
829 if (getClass() != obj.getClass())
830 {
831 return false;
832 }
833 final SerializedViewKey other = (SerializedViewKey) obj;
834 if (_sequenceId == null)
835 {
836 if (other._sequenceId != null)
837 {
838 return false;
839 }
840 }
841 else if (!_sequenceId.equals(other._sequenceId))
842 {
843 return false;
844 }
845 if (_viewId == null)
846 {
847 if (other._viewId != null)
848 {
849 return false;
850 }
851 }
852 else if (!_viewId.equals(other._viewId))
853 {
854 return false;
855 }
856 return true;
857 }
858
859 }
860
861
862
863 @Override
864 public Object saveSerializedView(FacesContext facesContext, Object serializedView)
865 {
866 if (log.isLoggable(Level.FINEST))
867 {
868 log.finest("Processing saveSerializedView - server-side state saving - save state");
869 }
870
871 saveSerializedViewInServletSession(facesContext, serializedView);
872
873 if (log.isLoggable(Level.FINEST))
874 {
875 log.finest("Exiting saveSerializedView - server-side state saving - saved state");
876 }
877
878 return encodeSerializedState(facesContext, serializedView);
879 }
880
881 @Override
882 public Object restoreSerializedView(FacesContext facesContext, String viewId, Object viewState)
883 {
884 if (log.isLoggable(Level.FINEST))
885 {
886 log.finest("Restoring view from session");
887 }
888
889 Integer serverStateId = getServerStateId((Object[]) viewState);
890
891 return (serverStateId == null)
892 ? null
893 : getSerializedViewFromServletSession(facesContext, viewId, serverStateId);
894 }
895
896 public Object encodeSerializedState(FacesContext facesContext, Object serializedView)
897 {
898 Object[] identifier = new Object[2];
899 identifier[JSF_SEQUENCE_INDEX] = Integer.toString(getNextViewSequence(facesContext), Character.MAX_RADIX);
900 return identifier;
901 }
902
903 @Override
904 public boolean isWriteStateAfterRenderViewRequired(FacesContext facesContext)
905 {
906 return false;
907 }
908
909
910
911 private boolean isUseFlashScopePurgeViewsInSession(ExternalContext externalContext)
912 {
913 if (_useFlashScopePurgeViewsInSession == null)
914 {
915 _useFlashScopePurgeViewsInSession = WebConfigParamUtils.getBooleanInitParameter(
916 externalContext, USE_FLASH_SCOPE_PURGE_VIEWS_IN_SESSION, false);
917 }
918 return _useFlashScopePurgeViewsInSession;
919 }
920
921 private Integer getNumberOfSequentialViewsInSession(ExternalContext externalContext)
922 {
923 if (!_numberOfSequentialViewsInSessionSet)
924 {
925 _numberOfSequentialViewsInSession = WebConfigParamUtils.getIntegerInitParameter(
926 externalContext,
927 NUMBER_OF_SEQUENTIAL_VIEWS_IN_SESSION_PARAM);
928 _numberOfSequentialViewsInSessionSet = true;
929 }
930 return _numberOfSequentialViewsInSession;
931 }
932 }