1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.shared.context.flash;
20
21 import org.apache.myfaces.shared.util.SubKeyMap;
22 import org.apache.myfaces.shared.util.ExternalContextUtils;
23
24 import jakarta.faces.application.FacesMessage;
25 import jakarta.faces.context.ExternalContext;
26 import jakarta.faces.context.FacesContext;
27 import jakarta.faces.context.Flash;
28 import jakarta.faces.event.PhaseId;
29 import jakarta.servlet.http.Cookie;
30 import jakarta.servlet.http.HttpServletResponse;
31 import java.io.Serializable;
32 import java.math.BigInteger;
33 import java.security.NoSuchAlgorithmException;
34 import java.security.SecureRandom;
35 import java.util.ArrayList;
36 import java.util.Collection;
37 import java.util.Collections;
38 import java.util.Iterator;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.Set;
42 import java.util.concurrent.atomic.AtomicLong;
43 import java.util.logging.Logger;
44 import jakarta.faces.event.PostKeepFlashValueEvent;
45 import jakarta.faces.event.PostPutFlashValueEvent;
46 import jakarta.faces.event.PreClearFlashEvent;
47 import jakarta.faces.event.PreRemoveFlashValueEvent;
48 import jakarta.faces.lifecycle.ClientWindow;
49 import org.apache.myfaces.shared.config.MyfacesConfig;
50
51
52
53
54 public class FlashImpl extends Flash implements ReleasableFlash
55 {
56
57
58
59 private static final Logger log = Logger.getLogger(FlashImpl.class.getName());
60
61
62
63
64
65
66 private static final String FLASH_PREFIX = "oam.Flash";
67
68
69
70
71 static final String FLASH_INSTANCE = FLASH_PREFIX + ".INSTANCE";
72
73
74
75
76
77 static final String FLASH_REDIRECT = FLASH_PREFIX + ".REDIRECT";
78
79
80
81
82 static final String FLASH_PREVIOUS_REQUEST_REDIRECT
83 = FLASH_PREFIX + ".REDIRECT.PREVIOUSREQUEST";
84
85
86
87
88 static final String FLASH_KEEP_MESSAGES = FLASH_PREFIX + ".KEEP_MESSAGES";
89
90
91
92
93 static final String FLASH_KEEP_MESSAGES_LIST = "KEEPMESSAGESLIST";
94
95
96
97
98 static final String FLASH_SESSION_MAP_SUBKEY_PREFIX = FLASH_PREFIX + ".SCOPE";
99
100
101
102
103 static final String FLASH_RENDER_MAP = FLASH_PREFIX + ".RENDERMAP";
104
105
106
107
108 static final String FLASH_RENDER_MAP_TOKEN = FLASH_PREFIX + ".RENDERMAP.TOKEN";
109
110
111
112
113 static final String FLASH_EXECUTE_MAP = FLASH_PREFIX + ".EXECUTEMAP";
114
115
116
117
118 static final String FLASH_EXECUTE_MAP_TOKEN = FLASH_PREFIX + ".EXECUTEMAP.TOKEN";
119
120 static final String FLASH_CW_LRU_MAP = FLASH_PREFIX + ".CW.LRUMAP";
121
122
123
124
125 static final char SEPARATOR_CHAR = '.';
126
127
128
129
130
131
132
133
134
135 public static Flash getCurrentInstance(ExternalContext context)
136 {
137 return getCurrentInstance(context, true);
138 }
139
140 public static Flash getCurrentInstance(ExternalContext context, boolean create)
141 {
142 Map<String, Object> applicationMap = context.getApplicationMap();
143
144 Flash flash = (Flash) applicationMap.get(FLASH_INSTANCE);
145 if (flash == null && create)
146 {
147
148
149 synchronized (applicationMap)
150 {
151
152 flash = (Flash) applicationMap.get(FLASH_INSTANCE);
153 if (flash == null)
154 {
155 flash = new FlashImpl(context);
156 applicationMap.put(FLASH_INSTANCE, flash);
157 }
158 }
159 }
160
161 return flash;
162 }
163
164
165
166
167 private static long _getSeed()
168 {
169 SecureRandom rng;
170 try
171 {
172
173 rng = SecureRandom.getInstance("SHA1PRNG");
174 }
175 catch (NoSuchAlgorithmException e)
176 {
177
178
179 rng = new SecureRandom();
180 }
181
182
183 byte[] randomBytes = new byte[6];
184 rng.nextBytes(randomBytes);
185
186
187 return new BigInteger(randomBytes).longValue();
188 }
189
190
191
192
193 private final AtomicLong _count;
194 private boolean _flashScopeDisabled;
195
196 public FlashImpl(ExternalContext externalContext)
197 {
198 _count = new AtomicLong(_getSeed());
199
200
201 _flashScopeDisabled = MyfacesConfig.getCurrentInstance(externalContext).isFlashScopeDisabled();
202 }
203
204
205
206
207
208
209
210
211 @Override
212 public void doPrePhaseActions(FacesContext facesContext)
213 {
214 if (!_flashScopeDisabled)
215 {
216 final PhaseId currentPhaseId = facesContext.getCurrentPhaseId();
217
218 if (PhaseId.RESTORE_VIEW.equals(currentPhaseId))
219 {
220
221
222
223 _restoreRedirectValue(facesContext);
224
225
226
227 _manageFlashMapTokens(facesContext);
228
229
230 _restoreMessages(facesContext);
231 }
232 }
233 }
234
235
236
237
238
239
240 @Override
241 public void doPostPhaseActions(FacesContext facesContext)
242 {
243 if (!_flashScopeDisabled)
244 {
245
246
247 if (_isLastPhaseInRequest(facesContext))
248 {
249 if (_isRedirectTrueOnThisRequest(facesContext))
250 {
251
252 Map<String, Object> renderMap = _getRenderFlashMap(facesContext);
253
254 for (Map.Entry<String, Object> entry
255 : _getExecuteFlashMap(facesContext).entrySet())
256 {
257 if (!renderMap.containsKey(entry.getKey()))
258 {
259 renderMap.put(entry.getKey(), entry.getValue());
260 }
261 }
262 }
263
264
265 _clearExecuteFlashMap(facesContext);
266
267
268
269
270
271 _saveMessages(facesContext);
272
273 _clearRenderFlashTokenIfMapEmpty(facesContext);
274 }
275 }
276 }
277
278
279
280
281
282
283
284
285
286
287
288 @Override
289 public boolean isRedirect()
290 {
291 FacesContext facesContext = FacesContext.getCurrentInstance();
292 boolean thisRedirect = _isRedirectTrueOnThisRequest(facesContext);
293 boolean prevRedirect = _isRedirectTrueOnPreviousRequest(facesContext);
294 boolean executePhase = !PhaseId.RENDER_RESPONSE.equals(facesContext.getCurrentPhaseId());
295
296 return thisRedirect || (executePhase && prevRedirect);
297 }
298
299 @Override
300 public void setRedirect(boolean redirect)
301 {
302
303
304
305
306
307
308 FacesContext facesContext = FacesContext.getCurrentInstance();
309 ExternalContext externalContext = facesContext.getExternalContext();
310 Map<String, Object> requestMap = externalContext.getRequestMap();
311
312
313 Boolean alreadySet = (Boolean) requestMap.get(FLASH_REDIRECT);
314 alreadySet = (alreadySet == null ? Boolean.FALSE : Boolean.TRUE);
315
316
317 if (!alreadySet && redirect)
318 {
319 requestMap.put(FLASH_REDIRECT, Boolean.TRUE);
320
321
322 _saveRedirectValue(facesContext);
323 }
324 else
325 {
326 if (alreadySet)
327 {
328 log.warning("Multiple call to setRedirect() ignored.");
329 }
330 else
331 {
332 log.warning("Ignored call to setRedirect(false), because this "
333 + "should only be set to true by the NavigationHandler. "
334 + "No one else should change it.");
335 }
336 }
337 }
338
339
340
341
342
343
344 @Override
345 public void keep(String key)
346 {
347 _checkFlashScopeDisabled();
348 FacesContext facesContext = FacesContext.getCurrentInstance();
349 Map<String, Object> requestMap = facesContext.getExternalContext().getRequestMap();
350 Object value = requestMap.get(key);
351
352
353
354 if (value == null)
355 {
356 Map<String, Object> executeMap = _getExecuteFlashMap(facesContext);
357
358
359 if (executeMap != null)
360 {
361 value = executeMap.get(key);
362
363
364
365 requestMap.put(key, value);
366 }
367 }
368
369
370 _getRenderFlashMap(facesContext).put(key, value);
371
372 facesContext.getApplication().publishEvent(facesContext,
373 PostKeepFlashValueEvent.class, key);
374 }
375
376
377
378
379 @Override
380 public void putNow(String key, Object value)
381 {
382 _checkFlashScopeDisabled();
383 FacesContext.getCurrentInstance().getExternalContext()
384 .getRequestMap().put(key, value);
385 }
386
387
388
389
390
391 @Override
392 public boolean isKeepMessages()
393 {
394 FacesContext facesContext = FacesContext.getCurrentInstance();
395 Boolean keepMessages = null;
396 if (facesContext != null)
397 {
398 ExternalContext externalContext = facesContext.getExternalContext();
399 Map<String, Object> requestMap = externalContext.getRequestMap();
400 keepMessages = (Boolean) requestMap.get(FLASH_KEEP_MESSAGES);
401 }
402
403 return (keepMessages == null ? Boolean.FALSE : keepMessages);
404 }
405
406
407
408
409
410
411
412
413
414
415
416 @Override
417 public void setKeepMessages(boolean keepMessages)
418 {
419 FacesContext facesContext = FacesContext.getCurrentInstance();
420 ExternalContext externalContext = facesContext.getExternalContext();
421 Map<String, Object> requestMap = externalContext.getRequestMap();
422 requestMap.put(FLASH_KEEP_MESSAGES, keepMessages);
423 }
424
425
426
427
428
429
430 public void clear()
431 {
432 _checkFlashScopeDisabled();
433 _getFlashMapForWriting().clear();
434 }
435
436 public boolean containsKey(Object key)
437 {
438 _checkFlashScopeDisabled();
439 return _getFlashMapForReading().containsKey(key);
440 }
441
442 public boolean containsValue(Object value)
443 {
444 _checkFlashScopeDisabled();
445 return _getFlashMapForReading().containsValue(value);
446 }
447
448 public Set<java.util.Map.Entry<String, Object>> entrySet()
449 {
450 _checkFlashScopeDisabled();
451 return _getFlashMapForReading().entrySet();
452 }
453
454 public Object get(Object key)
455 {
456 _checkFlashScopeDisabled();
457 if (key == null)
458 {
459 return null;
460 }
461
462 if ("keepMessages".equals(key))
463 {
464 return isKeepMessages();
465 }
466 else if ("redirect".equals(key))
467 {
468 return isRedirect();
469 }
470
471 return _getFlashMapForReading().get(key);
472 }
473
474 public boolean isEmpty()
475 {
476 _checkFlashScopeDisabled();
477 return _getFlashMapForReading().isEmpty();
478 }
479
480 public Set<String> keySet()
481 {
482 _checkFlashScopeDisabled();
483 return _getFlashMapForReading().keySet();
484 }
485
486 public Object put(String key, Object value)
487 {
488 _checkFlashScopeDisabled();
489 if (key == null)
490 {
491 return null;
492 }
493
494 if ("keepMessages".equals(key))
495 {
496 Boolean booleanValue = _convertToBoolean(value);
497 this.setKeepMessages(booleanValue);
498 return booleanValue;
499 }
500 else if ("redirect".equals(key))
501 {
502 Boolean booleanValue = _convertToBoolean(value);
503 this.setRedirect(booleanValue);
504 return booleanValue;
505 }
506 else
507 {
508 Object resp = _getFlashMapForWriting().put(key, value);
509
510 FacesContext facesContext = FacesContext.getCurrentInstance();
511 facesContext.getApplication().publishEvent(facesContext,
512 PostPutFlashValueEvent.class, key);
513
514 return resp;
515 }
516 }
517
518 public void putAll(Map<? extends String, ? extends Object> m)
519 {
520 _checkFlashScopeDisabled();
521 _getFlashMapForWriting().putAll(m);
522 }
523
524 public Object remove(Object key)
525 {
526 _checkFlashScopeDisabled();
527
528 FacesContext facesContext = FacesContext.getCurrentInstance();
529 facesContext.getApplication().publishEvent(facesContext,
530 PreRemoveFlashValueEvent.class, key);
531
532 return _getFlashMapForWriting().remove(key);
533 }
534
535 public int size()
536 {
537 _checkFlashScopeDisabled();
538 return _getFlashMapForReading().size();
539 }
540
541 public Collection<Object> values()
542 {
543 _checkFlashScopeDisabled();
544 return _getFlashMapForReading().values();
545 }
546
547
548
549
550
551
552
553
554
555
556
557 private boolean _isLastPhaseInRequest(FacesContext facesContext)
558 {
559 final PhaseId currentPhaseId = facesContext.getCurrentPhaseId();
560
561 boolean lastPhaseNormalRequest = PhaseId.RENDER_RESPONSE.equals(currentPhaseId);
562
563
564
565 boolean lastPhaseIfRedirect = facesContext.getResponseComplete()
566 && _isRedirectTrueOnThisRequest(facesContext);
567
568 return lastPhaseNormalRequest || lastPhaseIfRedirect;
569 }
570
571
572
573
574
575
576 private boolean _isRedirectTrueOnThisRequest(FacesContext facesContext)
577 {
578 ExternalContext externalContext = facesContext.getExternalContext();
579 Map<String, Object> requestMap = externalContext.getRequestMap();
580 Boolean redirect = (Boolean) requestMap.get(FLASH_REDIRECT);
581
582 return Boolean.TRUE.equals(redirect);
583 }
584
585
586
587
588
589
590
591 private boolean _isRedirectTrueOnPreviousRequest(FacesContext facesContext)
592 {
593 ExternalContext externalContext = facesContext.getExternalContext();
594 Map<String, Object> requestMap = externalContext.getRequestMap();
595 Boolean redirect = (Boolean) requestMap.get(FLASH_PREVIOUS_REQUEST_REDIRECT);
596
597 return Boolean.TRUE.equals(redirect);
598 }
599
600
601
602
603 private void _saveRedirectValue(FacesContext facesContext)
604 {
605 ExternalContext externalContext = facesContext.getExternalContext();
606
607
608
609
610
611
612
613 HttpServletResponse httpResponse = ExternalContextUtils
614 .getHttpServletResponse(externalContext);
615 if (httpResponse != null)
616 {
617 Cookie cookie = _createFlashCookie(FLASH_REDIRECT, "true", externalContext);
618 httpResponse.addCookie(cookie);
619 }
620 else
621 {
622 externalContext.getSessionMap().put(FLASH_REDIRECT, true);
623 }
624 }
625
626
627
628
629
630
631
632
633
634 private void _restoreRedirectValue(FacesContext facesContext)
635 {
636 ExternalContext externalContext = facesContext.getExternalContext();
637 HttpServletResponse httpResponse = ExternalContextUtils
638 .getHttpServletResponse(externalContext);
639 if (httpResponse != null)
640 {
641
642
643
644
645 Cookie cookie = (Cookie) externalContext
646 .getRequestCookieMap().get(FLASH_REDIRECT);
647 if (cookie != null)
648 {
649
650 externalContext.getRequestMap().put(
651 FLASH_PREVIOUS_REQUEST_REDIRECT, Boolean.TRUE);
652
653
654
655
656 cookie.setMaxAge(0);
657 cookie.setPath(_getCookiePath(externalContext));
658
659
660
661 httpResponse.addCookie(cookie);
662 }
663 }
664 else
665 {
666
667
668
669
670
671 Map<String, Object> sessionMap = externalContext.getSessionMap();
672
673
674 Boolean redirect = (Boolean) sessionMap.remove(FLASH_REDIRECT);
675
676
677 externalContext.getRequestMap().put(
678 FLASH_PREVIOUS_REQUEST_REDIRECT, redirect);
679 }
680 }
681
682
683
684
685
686
687
688 private void _saveMessages(FacesContext facesContext)
689 {
690 if (isKeepMessages())
691 {
692
693
694 List<MessageEntry> messageList = null;
695
696 Iterator<String> iterClientIds = facesContext.getClientIdsWithMessages();
697 while (iterClientIds.hasNext())
698 {
699 String clientId = (String) iterClientIds.next();
700 Iterator<FacesMessage> iterMessages = facesContext.getMessages(clientId);
701
702 while (iterMessages.hasNext())
703 {
704 FacesMessage message = iterMessages.next();
705
706 if (messageList == null)
707 {
708 messageList = new ArrayList<MessageEntry>();
709 }
710 messageList.add(new MessageEntry(clientId, message));
711 }
712 }
713
714 _getRenderFlashMap(facesContext).put(FLASH_KEEP_MESSAGES_LIST, messageList);
715 }
716 else
717 {
718
719 _getRenderFlashMap(facesContext).remove(FLASH_KEEP_MESSAGES_LIST);
720 }
721 }
722
723
724
725
726
727
728
729 @SuppressWarnings("unchecked")
730 private void _restoreMessages(FacesContext facesContext)
731 {
732 List<MessageEntry> messageList = (List<MessageEntry>)
733 _getExecuteFlashMap(facesContext).get(FLASH_KEEP_MESSAGES_LIST);
734
735 if (messageList != null)
736 {
737 Iterator<MessageEntry> iterMessages = messageList.iterator();
738
739 while (iterMessages.hasNext())
740 {
741 MessageEntry entry = iterMessages.next();
742 facesContext.addMessage(entry.clientId, entry.message);
743 }
744
745
746 _getExecuteFlashMap(facesContext).remove(FLASH_KEEP_MESSAGES_LIST);
747 }
748 }
749
750
751
752
753
754
755
756 private void _saveRenderFlashMapTokenForNextRequest(FacesContext facesContext)
757 {
758 ExternalContext externalContext = facesContext.getExternalContext();
759 String tokenValue = (String) externalContext.getRequestMap().get(FLASH_RENDER_MAP_TOKEN);
760 ClientWindow clientWindow = externalContext.getClientWindow();
761 if (clientWindow != null)
762 {
763 if (facesContext.getApplication().getStateManager().isSavingStateInClient(facesContext))
764 {
765
766 Map<String, Object> sessionMap = externalContext.getSessionMap();
767 sessionMap.put(FLASH_RENDER_MAP_TOKEN+SEPARATOR_CHAR+clientWindow.getId(), tokenValue);
768 }
769 else
770 {
771 FlashClientWindowTokenCollection lruMap = getFlashClientWindowTokenCollection(externalContext, true);
772 lruMap.put(clientWindow.getId(), tokenValue);
773 }
774 }
775 else
776 {
777 HttpServletResponse httpResponse = ExternalContextUtils.getHttpServletResponse(externalContext);
778 if (httpResponse != null)
779 {
780 Cookie cookie = _createFlashCookie(FLASH_RENDER_MAP_TOKEN, tokenValue, externalContext);
781 httpResponse.addCookie(cookie);
782 }
783 else
784 {
785
786 Map<String, Object> sessionMap = externalContext.getSessionMap();
787 sessionMap.put(FLASH_RENDER_MAP_TOKEN, tokenValue);
788 }
789 }
790 }
791
792
793
794
795
796
797
798
799
800 private String _getRenderFlashMapTokenFromPreviousRequest(FacesContext facesContext)
801 {
802 ExternalContext externalContext = facesContext.getExternalContext();
803 String tokenValue = null;
804 ClientWindow clientWindow = externalContext.getClientWindow();
805 if (clientWindow != null)
806 {
807 if (facesContext.getApplication().getStateManager().isSavingStateInClient(facesContext))
808 {
809 Map<String, Object> sessionMap = externalContext.getSessionMap();
810 tokenValue = (String) sessionMap.get(FLASH_RENDER_MAP_TOKEN+
811 SEPARATOR_CHAR+clientWindow.getId());
812 }
813 else
814 {
815 FlashClientWindowTokenCollection lruMap = getFlashClientWindowTokenCollection(externalContext, false);
816 if (lruMap != null)
817 {
818 tokenValue = (String) lruMap.get(clientWindow.getId());
819 }
820 }
821 }
822 else
823 {
824 HttpServletResponse httpResponse = ExternalContextUtils.getHttpServletResponse(externalContext);
825 if (httpResponse != null)
826 {
827
828 Cookie cookie = (Cookie) externalContext.getRequestCookieMap().get(FLASH_RENDER_MAP_TOKEN);
829 if (cookie != null)
830 {
831 tokenValue = cookie.getValue();
832 }
833 }
834 else
835 {
836
837 Map<String, Object> sessionMap = externalContext.getSessionMap();
838 tokenValue = (String) sessionMap.get(FLASH_RENDER_MAP_TOKEN);
839 }
840 }
841 return tokenValue;
842 }
843
844
845
846
847
848
849
850
851 private void _manageFlashMapTokens(FacesContext facesContext)
852 {
853 ExternalContext externalContext = facesContext.getExternalContext();
854 Map<String, Object> requestMap = externalContext.getRequestMap();
855
856 final String previousRenderToken
857 = _getRenderFlashMapTokenFromPreviousRequest(facesContext);
858 if (previousRenderToken != null)
859 {
860
861
862 requestMap.put(FLASH_EXECUTE_MAP_TOKEN, previousRenderToken);
863 }
864 else
865 {
866 if (facesContext.isPostback())
867 {
868 if (facesContext.getExternalContext().getClientWindow() == null)
869 {
870
871 log.warning("Identifier for execute FlashMap was lost on " +
872 "the postback, thus FlashScope information is gone.");
873 }
874 else
875 {
876
877
878
879 requestMap.put(FLASH_EXECUTE_MAP_TOKEN, _getNextToken());
880 }
881 }
882
883
884
885 final String newExecuteToken = _getNextToken();
886 requestMap.put(FLASH_EXECUTE_MAP_TOKEN, newExecuteToken);
887 }
888
889
890 final String newRenderToken = _getNextToken();
891 requestMap.put(FLASH_RENDER_MAP_TOKEN, newRenderToken);
892
893
894
895 _saveRenderFlashMapTokenForNextRequest(facesContext);
896 }
897
898
899
900
901
902
903 private String _getNextToken()
904 {
905
906 long nextToken = _count.incrementAndGet();
907
908
909 return Long.toString(nextToken, 36);
910 }
911
912
913
914
915
916
917 private Map<String, Object> _createSubKeyMap(FacesContext context, String prefix)
918 {
919 ExternalContext external = context.getExternalContext();
920 Map<String, Object> sessionMap = external.getSessionMap();
921
922 return new SubKeyMap<Object>(sessionMap, prefix);
923 }
924
925
926
927
928
929
930
931
932
933
934
935
936 @SuppressWarnings("unchecked")
937 private Map<String, Object> _getRenderFlashMap(FacesContext context)
938 {
939
940
941
942
943 Map<String, Object> requestMap = context.getExternalContext().getRequestMap();
944 Map<String, Object> map = (Map<String, Object>) requestMap.get(FLASH_RENDER_MAP);
945 if (map == null)
946 {
947 String token = (String) requestMap.get(FLASH_RENDER_MAP_TOKEN);
948 String fullToken = FLASH_SESSION_MAP_SUBKEY_PREFIX + SEPARATOR_CHAR + token + SEPARATOR_CHAR;
949 map = _createSubKeyMap(context, fullToken);
950 requestMap.put(FLASH_RENDER_MAP, map);
951 }
952 return map;
953 }
954
955
956
957
958
959
960
961
962
963 @SuppressWarnings("unchecked")
964 private Map<String, Object> _getExecuteFlashMap(FacesContext context)
965 {
966
967
968
969
970 Map<String, Object> requestMap = context != null && context.getExternalContext() != null ?
971 context.getExternalContext().getRequestMap() : null;
972 Map<String, Object> map = requestMap != null ? (Map<String, Object>) requestMap.get(FLASH_EXECUTE_MAP) : null;
973 if (map == null)
974 {
975 if (requestMap != null)
976 {
977 String token = (String) requestMap.get(FLASH_EXECUTE_MAP_TOKEN);
978 String fullToken = FLASH_SESSION_MAP_SUBKEY_PREFIX + SEPARATOR_CHAR + token + SEPARATOR_CHAR;
979 map = _createSubKeyMap(context, fullToken);
980 requestMap.put(FLASH_EXECUTE_MAP, map);
981 }
982 else
983 {
984 map = Collections.emptyMap();
985 }
986 }
987 return map;
988 }
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036 private Map<String, Object> _getActiveFlashMap()
1037 {
1038 FacesContext facesContext = FacesContext.getCurrentInstance();
1039 if (PhaseId.RENDER_RESPONSE.equals(facesContext.getCurrentPhaseId())
1040 || !facesContext.isPostback())
1041 {
1042 return _getRenderFlashMap(facesContext);
1043 }
1044 else
1045 {
1046 return _getExecuteFlashMap(facesContext);
1047 }
1048 }
1049
1050
1051
1052
1053
1054
1055 private Map<String, Object> _getFlashMapForReading()
1056 {
1057 return _getExecuteFlashMap(FacesContext.getCurrentInstance());
1058 }
1059
1060
1061
1062
1063
1064
1065 private Map<String, Object> _getFlashMapForWriting()
1066 {
1067 return _getActiveFlashMap();
1068 }
1069
1070
1071
1072
1073
1074 private void _clearExecuteFlashMap(FacesContext facesContext)
1075 {
1076 Map<String, Object> map = _getExecuteFlashMap(facesContext);
1077
1078 if (!map.isEmpty())
1079 {
1080
1081 facesContext.getApplication().publishEvent(facesContext,
1082 PreClearFlashEvent.class, map);
1083
1084
1085
1086
1087
1088
1089
1090
1091 map.clear();
1092 }
1093 }
1094
1095 private void _clearRenderFlashTokenIfMapEmpty(FacesContext facesContext)
1096 {
1097
1098
1099
1100
1101 ExternalContext externalContext = facesContext.getExternalContext();
1102 Object session = facesContext.getExternalContext().getSession(false);
1103 ClientWindow clientWindow = externalContext.getClientWindow();
1104 if (session != null && clientWindow != null)
1105 {
1106 Map<String, Object> map = _getRenderFlashMap(facesContext);
1107 if (map.isEmpty())
1108 {
1109 if (facesContext.getApplication().getStateManager().isSavingStateInClient(facesContext))
1110 {
1111 Map<String, Object> sessionMap = externalContext.getSessionMap();
1112 sessionMap.remove(FLASH_RENDER_MAP_TOKEN+SEPARATOR_CHAR+clientWindow.getId());
1113 }
1114 else
1115 {
1116
1117 FlashClientWindowTokenCollection lruMap = getFlashClientWindowTokenCollection(
1118 externalContext, false);
1119 if (lruMap != null)
1120 {
1121 lruMap.remove(clientWindow.getId());
1122 Map<String, Object> sessionMap = externalContext.getSessionMap();
1123 if (lruMap.isEmpty())
1124 {
1125 sessionMap.remove(FLASH_CW_LRU_MAP);
1126 }
1127 else
1128 {
1129
1130 sessionMap.put(FLASH_CW_LRU_MAP, lruMap);
1131 }
1132 }
1133 }
1134 }
1135 }
1136 }
1137
1138 protected FlashClientWindowTokenCollection getFlashClientWindowTokenCollection(
1139 ExternalContext externalContext, boolean create)
1140 {
1141 Object session = externalContext.getSession(false);
1142 if (session == null && !create)
1143 {
1144 return null;
1145 }
1146 Map<String, Object> sessionMap = externalContext.getSessionMap();
1147 FlashClientWindowTokenCollection lruMap = (FlashClientWindowTokenCollection)
1148 sessionMap.get(FLASH_CW_LRU_MAP);
1149 if (lruMap == null)
1150 {
1151 Integer ft = MyfacesConfig.getCurrentInstance(externalContext).getNumberOfFlashTokensInSession();
1152 lruMap = new FlashClientWindowTokenCollection(new ClientWindowFlashTokenLRUMap(ft));
1153 }
1154
1155 if (create)
1156 {
1157 sessionMap.put(FLASH_CW_LRU_MAP, lruMap);
1158 }
1159 return lruMap;
1160 }
1161
1162 public void clearFlashMap(FacesContext facesContext, String clientWindowId, String token)
1163 {
1164 if ((!_flashScopeDisabled) &&
1165 (!facesContext.getApplication().getStateManager().isSavingStateInClient(facesContext)))
1166 {
1167 ExternalContext externalContext = facesContext.getExternalContext();
1168 ClientWindow clientWindow = externalContext.getClientWindow();
1169 if (clientWindow != null)
1170 {
1171 if (token != null)
1172 {
1173 String fullToken = FLASH_SESSION_MAP_SUBKEY_PREFIX + SEPARATOR_CHAR + token + SEPARATOR_CHAR;
1174 Map<String, Object> map = _createSubKeyMap(facesContext, fullToken);
1175 map.clear();
1176 }
1177 }
1178 }
1179 }
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190 private Cookie _createFlashCookie(String name, String value, ExternalContext externalContext)
1191 {
1192 Cookie cookie = new Cookie(name, value);
1193
1194 cookie.setMaxAge(-1);
1195 cookie.setPath(_getCookiePath(externalContext));
1196 cookie.setSecure(externalContext.isSecure());
1197 cookie.setHttpOnly(true);
1198 return cookie;
1199 }
1200
1201
1202
1203
1204
1205
1206 private String _getCookiePath(ExternalContext externalContext)
1207 {
1208 String contextPath = externalContext.getRequestContextPath();
1209
1210 if (contextPath == null || "".equals(contextPath))
1211 {
1212 contextPath = "/";
1213 }
1214
1215 return contextPath;
1216 }
1217
1218
1219
1220
1221
1222
1223 private Boolean _convertToBoolean(Object value)
1224 {
1225 Boolean booleanValue;
1226 if (value instanceof Boolean)
1227 {
1228 booleanValue = (Boolean) value;
1229 }
1230 else
1231 {
1232 booleanValue = Boolean.parseBoolean(value.toString());
1233 }
1234 return booleanValue;
1235 }
1236
1237
1238
1239
1240
1241 private void _checkFlashScopeDisabled()
1242 {
1243 if (_flashScopeDisabled)
1244 {
1245 throw new FlashScopeDisabledException("Flash scope was disabled by context param "
1246 + MyfacesConfig.INIT_PARAM_FLASH_SCOPE_DISABLED + " but erroneously accessed");
1247 }
1248 }
1249
1250
1251
1252
1253
1254
1255 private static class MessageEntry implements Serializable
1256 {
1257 private static final long serialVersionUID = -690264660230199234L;
1258 private final String clientId;
1259 private final FacesMessage message;
1260
1261 public MessageEntry(String clientId, FacesMessage message)
1262 {
1263 this.clientId = clientId;
1264 this.message = message;
1265 }
1266 }
1267
1268 }