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