1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.view.facelets;
20
21 import java.util.ArrayList;
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.logging.Level;
26 import java.util.logging.Logger;
27 import javax.faces.application.Application;
28 import javax.faces.application.NavigationHandler;
29 import javax.faces.application.ProjectStage;
30 import javax.faces.application.ResourceDependency;
31 import javax.faces.application.ViewHandler;
32 import javax.faces.component.UIComponent;
33 import javax.faces.component.UIViewRoot;
34 import javax.faces.context.FacesContext;
35 import javax.faces.event.PhaseId;
36 import javax.faces.view.StateManagementStrategy;
37 import javax.faces.view.ViewDeclarationLanguage;
38 import org.apache.myfaces.application.StateManagerImpl;
39 import org.apache.myfaces.component.ComponentResourceContainer;
40 import org.apache.myfaces.context.RequestViewContext;
41 import org.apache.myfaces.context.RequestViewMetadata;
42 import org.apache.myfaces.lifecycle.DefaultRestoreViewSupport;
43 import org.apache.myfaces.lifecycle.RestoreViewSupport;
44 import org.apache.myfaces.shared.config.MyfacesConfig;
45 import org.apache.myfaces.shared.util.WebConfigParamUtils;
46 import org.apache.myfaces.view.facelets.impl.FaceletCompositionContextImpl;
47 import org.apache.myfaces.view.facelets.pool.ViewPool;
48 import org.apache.myfaces.view.facelets.pool.ViewPoolFactory;
49 import org.apache.myfaces.view.facelets.pool.ViewEntry;
50 import org.apache.myfaces.view.facelets.pool.ViewStructureMetadata;
51 import org.apache.myfaces.view.facelets.pool.impl.ViewPoolFactoryImpl;
52 import org.apache.myfaces.view.facelets.tag.jsf.ComponentSupport;
53 import org.apache.myfaces.view.facelets.tag.jsf.FaceletState;
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76 public class ViewPoolProcessor
77 {
78
79
80
81
82
83
84 private final static String INSTANCE = "oam.ViewPoolProcessor";
85
86
87
88
89 public final static String ENABLE_VIEW_POOL = "oamEnableViewPool";
90
91
92
93
94
95
96 public final static String FORCE_HARD_RESET = "oam.ViewPool.forceHardReset";
97
98
99
100
101 public final static String DISPOSE_VIEW_NAVIGATION = "oam.ViewPool.disposeViewOnNavigation";
102
103
104
105
106
107 public final static String RESET_SAVE_STATE_MODE_KEY ="oam.view.resetSaveStateMode";
108
109
110
111
112 public static final int RESET_MODE_OFF = 0;
113
114
115
116
117
118
119 public static final int RESET_MODE_SOFT = 1;
120
121
122
123
124
125
126
127
128
129 public static final int RESET_MODE_HARD = 2;
130
131
132
133
134
135
136
137
138
139 public static final String INVOKE_DEFERRED_NAVIGATION = "oam.invoke.navigation";
140
141 private ViewPoolFactory viewPoolFactory;
142 private RestoreViewSupport restoreViewSupport;
143
144 public ViewPoolProcessor(FacesContext context)
145 {
146 viewPoolFactory = new ViewPoolFactoryImpl(context);
147 restoreViewSupport = new DefaultRestoreViewSupport(context);
148 }
149
150 public static ViewPoolProcessor getInstance(FacesContext context)
151 {
152 return (ViewPoolProcessor) context.getExternalContext().
153 getApplicationMap().get(INSTANCE);
154 }
155
156
157
158
159
160
161
162 public static void initialize(FacesContext context)
163 {
164 if (context.isProjectStage(ProjectStage.Production))
165 {
166 boolean initialize = true;
167 String elMode = WebConfigParamUtils.getStringInitParameter(
168 context.getExternalContext(),
169 FaceletCompositionContextImpl.INIT_PARAM_CACHE_EL_EXPRESSIONS,
170 ELExpressionCacheMode.noCache.name());
171 if (!elMode.equals(ELExpressionCacheMode.alwaysRecompile.name()))
172 {
173 Logger.getLogger(ViewPoolProcessor.class.getName()).log(
174 Level.INFO, FaceletCompositionContextImpl.INIT_PARAM_CACHE_EL_EXPRESSIONS +
175 " web config parameter is set to \"" + ( (elMode == null) ? "none" : elMode) +
176 "\". To enable view pooling this param"+
177 " must be set to \"alwaysRecompile\". View Pooling disabled.");
178 initialize = false;
179 }
180
181 long refreshPeriod = WebConfigParamUtils.getLongInitParameter(context.getExternalContext(),
182 FaceletViewDeclarationLanguage.PARAMS_REFRESH_PERIOD,
183 FaceletViewDeclarationLanguage.DEFAULT_REFRESH_PERIOD_PRODUCTION);
184
185 if (refreshPeriod != -1)
186 {
187 Logger.getLogger(ViewPoolProcessor.class.getName()).log(
188 Level.INFO, ViewHandler.FACELETS_REFRESH_PERIOD_PARAM_NAME +
189 " web config parameter is set to \"" + Long.toString(refreshPeriod) +
190 "\". To enable view pooling this param"+
191 " must be set to \"-1\". View Pooling disabled.");
192 initialize = false;
193 }
194
195 if (MyfacesConfig.getCurrentInstance(context.getExternalContext()).isStrictJsf2FaceletsCompatibility())
196 {
197 Logger.getLogger(ViewPoolProcessor.class.getName()).log(
198 Level.INFO, MyfacesConfig.INIT_PARAM_STRICT_JSF_2_FACELETS_COMPATIBILITY +
199 " web config parameter is set to \"" + "true" +
200 "\". To enable view pooling this param "+
201 " must be set to \"false\". View Pooling disabled.");
202 initialize = false;
203 }
204
205 if (initialize)
206 {
207 ViewPoolProcessor processor = new ViewPoolProcessor(context);
208 context.getExternalContext().
209 getApplicationMap().put(INSTANCE, processor);
210 }
211 }
212 }
213
214 public ViewPool getViewPool(FacesContext context, UIViewRoot root)
215 {
216 if (root.isTransient())
217 {
218
219
220 return null;
221 }
222 Boolean enableViewPool = (Boolean) root.getAttributes().get(ViewPoolProcessor.ENABLE_VIEW_POOL);
223 if (enableViewPool != null && !Boolean.TRUE.equals(enableViewPool))
224 {
225
226 return null;
227 }
228 else
229 {
230 return viewPoolFactory.getViewPool(context, root);
231 }
232 }
233
234 public boolean isViewPoolEnabledForThisView(FacesContext context, UIViewRoot root)
235 {
236 if (root.isTransient())
237 {
238
239
240 return false;
241 }
242 Boolean enableViewPool = (Boolean) root.getAttributes().get(ViewPoolProcessor.ENABLE_VIEW_POOL);
243 if (enableViewPool != null)
244 {
245 if (Boolean.TRUE.equals(enableViewPool))
246 {
247 return true;
248 }
249 else
250 {
251 return false;
252 }
253 }
254 else
255 {
256 ViewPool viewPool = getViewPool(context, root);
257 if (viewPool != null)
258 {
259 return true;
260 }
261 }
262 return false;
263 }
264
265 public boolean isViewPoolStrategyAllowedForThisView(FacesContext context, UIViewRoot root)
266 {
267
268 if (root.getViewId() == null)
269 {
270 return false;
271 }
272 if (root.isTransient())
273 {
274
275
276 return false;
277 }
278
279
280 if (!isViewPoolEnabledForThisView(context, root))
281 {
282 return false;
283 }
284
285
286 ViewDeclarationLanguage vdl = context.getApplication().getViewHandler().
287 getViewDeclarationLanguage(context, root.getViewId());
288 if (vdl == null)
289 {
290 return false;
291 }
292 else if (!ViewDeclarationLanguage.FACELETS_VIEW_DECLARATION_LANGUAGE_ID.equals(vdl.getId()))
293 {
294 return false;
295 }
296
297 if (vdl.getStateManagementStrategy(context, root.getViewId()) == null)
298 {
299 return false;
300 }
301 return true;
302 }
303
304 public void setViewPoolDisabledOnThisView(FacesContext context, UIViewRoot root, boolean value)
305 {
306 root.getAttributes().put(ViewPoolProcessor.ENABLE_VIEW_POOL, !value);
307 }
308
309
310
311
312
313
314
315
316
317
318 public void cloneAndRestoreView(FacesContext context, UIViewRoot newView,
319 ViewEntry entry, ViewStructureMetadata metadata)
320 {
321 UIViewRoot oldView = entry.getViewRoot();
322
323 Object viewState = metadata.getViewRootState();
324 Object newViewState;
325 UIComponent metadataFacet = newView.getFacet(UIViewRoot.METADATA_FACET_NAME);
326 if (viewState == null)
327 {
328
329 oldView.clearInitialState();
330 viewState = oldView.saveState(context);
331 }
332 Map<String, Object> viewScopeMap = newView.getViewMap(false);
333 if (viewScopeMap != null && !viewScopeMap.isEmpty())
334 {
335 newViewState = newView.saveState(context);
336 }
337 else
338 {
339 newViewState = null;
340 }
341
342 boolean oldProcessingEvents = context.isProcessingEvents();
343 context.setProcessingEvents(false);
344 try
345 {
346 if (oldView.getFacetCount() > 0)
347 {
348 List<String> facetKeys = new ArrayList<String>();
349 facetKeys.addAll(oldView.getFacets().keySet());
350 for (String facetKey : facetKeys)
351 {
352
353 if (metadataFacet != null && UIViewRoot.METADATA_FACET_NAME.equals(facetKey) &&
354 !PhaseId.RESTORE_VIEW.equals(context.getCurrentPhaseId()))
355 {
356
357
358
359
360
361 newView.getFacets().put(facetKey, metadataFacet);
362 }
363 else
364 {
365 UIComponent facet = oldView.getFacets().remove(facetKey);
366
367 newView.getFacets().put(facetKey, facet);
368 }
369 }
370 }
371 if (oldView.getChildCount() > 0)
372 {
373 for (Iterator<UIComponent> it = oldView.getChildren().iterator(); it.hasNext();)
374 {
375
376 UIComponent c = it.next();
377 it.remove();
378
379 newView.getChildren().add(c);
380 }
381 }
382
383
384 newView.restoreState(context, viewState);
385 newView.markInitialState();
386
387 if (!PhaseId.RESTORE_VIEW.equals(context.getCurrentPhaseId()))
388 {
389
390
391 restoreViewSupport.processComponentBinding(context, newView);
392
393
394 if (viewScopeMap != null && !viewScopeMap.isEmpty())
395 {
396 Map<String, Object> newViewScopeMap = newView.getViewMap(false);
397 if (newViewScopeMap == null)
398 {
399 newView.restoreViewScopeState(context, newViewState);
400 }
401 else
402 {
403
404
405
406
407 for (Map.Entry<String, Object> entry2 : viewScopeMap.entrySet())
408 {
409 newViewScopeMap.put(entry2.getKey(), entry2.getValue());
410 }
411 }
412 }
413 }
414
415
416
417
418 RequestViewContext rcv = RequestViewContext.getCurrentInstance(context, newView, false);
419 if (rcv != null)
420 {
421 rcv.setRequestViewMetadata(metadata.getRequestViewMetadata().cloneInstance());
422 }
423 else
424 {
425 RequestViewContext.setCurrentInstance(context, newView,
426 RequestViewContext.newInstance(metadata.getRequestViewMetadata().cloneInstance()));
427 }
428 }
429 finally
430 {
431 context.setProcessingEvents(oldProcessingEvents);
432 }
433 }
434
435 public void storeViewStructureMetadata(FacesContext context, UIViewRoot root)
436 {
437 ViewPool viewPool = getViewPool(context, root);
438 if (viewPool != null)
439 {
440 FaceletState faceletState = (FaceletState) root.getAttributes().get(
441 ComponentSupport.FACELET_STATE_INSTANCE);
442 boolean isDynamic = faceletState != null ? faceletState.isDynamic() : false;
443 if (!isDynamic)
444 {
445 viewPool.storeStaticViewStructureMetadata(context, root, faceletState);
446 }
447 else
448 {
449 viewPool.storeDynamicViewStructureMetadata(context, root, faceletState);
450 }
451 }
452 }
453
454 public ViewStructureMetadata retrieveViewStructureMetadata(FacesContext context,
455 UIViewRoot root)
456 {
457 ViewPool viewPool = getViewPool(context, root);
458 if (viewPool != null)
459 {
460 FaceletState faceletState = (FaceletState) root.getAttributes().get(
461 ComponentSupport.FACELET_STATE_INSTANCE);
462 boolean isDynamic = faceletState != null ? faceletState.isDynamic() : false;
463 if (!isDynamic)
464 {
465 return viewPool.retrieveStaticViewStructureMetadata(context, root);
466 }
467 else
468 {
469 return viewPool.retrieveDynamicViewStructureMetadata(context, root, faceletState);
470 }
471 }
472 return null;
473 }
474
475 public void pushResetableView(FacesContext context, UIViewRoot view, FaceletState faceletViewState)
476 {
477 ViewPool viewPool = getViewPool(context, view);
478 if (viewPool != null)
479 {
480 boolean isDynamic = faceletViewState != null ? faceletViewState.isDynamic() : false;
481 if (!isDynamic)
482 {
483 clearTransientAndNonFaceletComponentsForStaticView(context, view);
484 viewPool.pushStaticStructureView(context, view);
485 }
486 else
487 {
488 ViewStructureMetadata viewStructureMetadata = viewPool.retrieveDynamicViewStructureMetadata(
489 context, view, faceletViewState);
490 if (viewStructureMetadata != null)
491 {
492 clearTransientAndNonFaceletComponentsForDynamicView(context, view, viewStructureMetadata);
493 viewPool.pushDynamicStructureView(context, view, faceletViewState);
494 }
495 }
496 }
497 }
498
499 public void pushPartialView(FacesContext context, UIViewRoot view, FaceletState faceletViewState, int count)
500 {
501 ViewPool viewPool = getViewPool(context, view);
502
503 if (viewPool != null && viewPool.isWorthToRecycleThisView(context, view))
504 {
505 ViewStructureMetadata viewStructureMetadata = null;
506 if (faceletViewState == null)
507 {
508 viewStructureMetadata = viewPool.retrieveStaticViewStructureMetadata(context, view);
509 }
510 else
511 {
512 viewStructureMetadata = viewPool.retrieveDynamicViewStructureMetadata(
513 context, view, faceletViewState);
514 }
515 if (viewStructureMetadata != null)
516 {
517 ClearPartialTreeContext ptc = new ClearPartialTreeContext();
518
519 clearTransientAndRemoveNonResetableComponents(context, ptc, view, viewStructureMetadata);
520 int reusableCount = ptc.getCount();
521 float factor = ((float)reusableCount) / ((float)count);
522 if (factor > 0.3f)
523 {
524 viewPool.pushPartialStructureView(context, view);
525 }
526 }
527 }
528 }
529
530 protected void clearTransientAndNonFaceletComponentsForStaticView(final FacesContext context,
531 final UIViewRoot root)
532 {
533
534
535 clearTransientAndNonFaceletComponents(context, root);
536 }
537
538 public void clearTransientAndNonFaceletComponentsForDynamicView(final FacesContext context,
539 final UIViewRoot root, final ViewStructureMetadata viewStructureMetadata)
540 {
541
542 int childCount = root.getChildCount();
543 if (childCount > 0)
544 {
545 for (int i = 0; i < childCount; i++)
546 {
547 UIComponent child = root.getChildren().get(i);
548 if (child != null && child.isTransient() &&
549 child.getAttributes().get(ComponentSupport.MARK_CREATED) == null)
550 {
551 root.getChildren().remove(i);
552 i--;
553 childCount--;
554 }
555 else
556 {
557 if (child.getChildCount() > 0 || !child.getFacets().isEmpty())
558 {
559 clearTransientAndNonFaceletComponents(context, child);
560 }
561 }
562 }
563 }
564
565 clearTransientAndNonFaceletComponentsForDynamicViewUIViewRootFacets(
566 context, root, viewStructureMetadata);
567 }
568
569 private void clearTransientAndNonFaceletComponentsForDynamicViewUIViewRootFacets(final FacesContext context,
570 final UIViewRoot root, ViewStructureMetadata viewStructureMetadata)
571 {
572
573
574 if (root.getFacetCount() > 0)
575 {
576 Map<String, UIComponent> facets = root.getFacets();
577 for (Iterator<UIComponent> itr = facets.values().iterator(); itr.hasNext();)
578 {
579 UIComponent fc = itr.next();
580 if (fc != null && !(fc instanceof ComponentResourceContainer))
581 {
582 if ( fc.isTransient() &&
583 fc.getAttributes().get(ComponentSupport.MARK_CREATED) == null)
584 {
585 itr.remove();
586 }
587 else
588 {
589 if (fc.getChildCount() > 0 || !fc.getFacets().isEmpty())
590 {
591 clearTransientAndNonFaceletComponents(context, fc);
592 }
593 }
594 }
595 else if (fc != null)
596 {
597
598
599
600
601 if (fc.getId() != null && fc.getId().startsWith("javax_faces_location_"))
602 {
603 String target = fc.getId().substring("javax_faces_location_".length());
604 Map<String, List<ResourceDependency>> addedResources =
605 viewStructureMetadata.getRequestViewMetadata().
606 getResourceDependencyAnnotations(context);
607 List<ResourceDependency> resourceDependencyList = (addedResources != null) ?
608 addedResources.get(target) : null;
609
610 clearComponentResourceContainer(context, fc, resourceDependencyList);
611 }
612 }
613 }
614 }
615 }
616
617 private void clearComponentResourceContainer(final FacesContext context, UIComponent component,
618 List<ResourceDependency> resourceDependencyList)
619 {
620
621 int childCount = component.getChildCount();
622 if (childCount > 0)
623 {
624 for (int i = 0; i < childCount; i++)
625 {
626 UIComponent child = component.getChildren().get(i);
627 String id = (String) child.getAttributes().get(ComponentSupport.MARK_CREATED);
628 if (child != null && child.isTransient() &&
629 id == null)
630 {
631
632 component.getChildren().remove(i);
633 i--;
634 childCount--;
635 }
636 else if (id != null)
637 {
638
639
640 }
641
642
643
644
645
646
647
648
649
650
651 else
652 {
653
654 Object[] rdk = (Object[]) child.getAttributes().get(
655 RequestViewMetadata.RESOURCE_DEPENDENCY_KEY);
656 if (rdk != null)
657 {
658 boolean found = false;
659 String library = (String) rdk[0];
660 String name = (String) rdk[1];
661 if (resourceDependencyList != null)
662 {
663 for (ResourceDependency resource : resourceDependencyList)
664 {
665 if (library == null && resource.library() == null)
666 {
667 if (name != null && name.equals(resource.name()))
668 {
669 found = true;
670 break;
671 }
672 }
673 else
674 {
675 if (library != null && library.equals(resource.library()) &&
676 name != null && name.equals(resource.name()) )
677 {
678 found = true;
679 break;
680 }
681 }
682 }
683 }
684 if (!found)
685 {
686
687 component.getChildren().remove(i);
688 i--;
689 childCount--;
690 }
691
692 }
693 else
694 {
695 if (child.getChildCount() > 0 || !child.getFacets().isEmpty())
696 {
697 clearTransientAndNonFaceletComponents(context, child);
698 }
699 }
700 }
701 }
702 }
703 }
704
705
706
707
708
709
710
711
712 private void clearTransientAndNonFaceletComponents(final FacesContext context, final UIComponent component)
713 {
714
715 int childCount = component.getChildCount();
716 if (childCount > 0)
717 {
718 for (int i = 0; i < childCount; i++)
719 {
720 UIComponent child = component.getChildren().get(i);
721 if (child != null && child.isTransient() &&
722 child.getAttributes().get(ComponentSupport.MARK_CREATED) == null)
723 {
724 component.getChildren().remove(i);
725 i--;
726 childCount--;
727 }
728 else
729 {
730 if (child.getChildCount() > 0 || !child.getFacets().isEmpty())
731 {
732 clearTransientAndNonFaceletComponents(context, child);
733 }
734 }
735 }
736 }
737
738
739 if (component.getFacetCount() > 0)
740 {
741 Map<String, UIComponent> facets = component.getFacets();
742 for (Iterator<UIComponent> itr = facets.values().iterator(); itr.hasNext();)
743 {
744 UIComponent fc = itr.next();
745 if (fc != null && fc.isTransient() &&
746 fc.getAttributes().get(ComponentSupport.MARK_CREATED) == null)
747 {
748 itr.remove();
749 }
750 else
751 {
752 if (fc.getChildCount() > 0 || !fc.getFacets().isEmpty())
753 {
754 clearTransientAndNonFaceletComponents(context, fc);
755 }
756 }
757 }
758 }
759 }
760
761 private void clearTransientAndRemoveNonResetableComponents(final FacesContext context,
762 final ClearPartialTreeContext ptc, final UIViewRoot root,
763 ViewStructureMetadata viewStructureMetadata)
764 {
765
766 int childCount = root.getChildCount();
767
768 try
769 {
770 root.getAttributes().put(ViewPoolProcessor.RESET_SAVE_STATE_MODE_KEY,
771 ViewPoolProcessor.RESET_MODE_HARD);
772 if (childCount > 0)
773 {
774 for (int i = 0; i < childCount; i++)
775 {
776 UIComponent child = root.getChildren().get(i);
777 boolean containsFaceletId = child.getAttributes().containsKey(ComponentSupport.MARK_CREATED);
778 if (child != null && child.isTransient() && !containsFaceletId)
779 {
780
781 root.getChildren().remove(i);
782 i--;
783 childCount--;
784 }
785 else
786 {
787 if (child.getAttributes().containsKey(ComponentSupport.COMPONENT_ADDED_BY_HANDLER_MARKER))
788 {
789
790 root.getChildren().remove(i);
791 i--;
792 childCount--;
793
794 }
795 else if (containsFaceletId ||
796 child.getAttributes().containsKey(ComponentSupport.COMPONENT_ADDED_BY_HANDLER_MARKER))
797 {
798
799
800
801 if (!child.isTransient())
802 {
803
804 Object state = child.saveState(context);
805 if (state == null)
806 {
807 if (child.getChildCount() > 0 || !child.getFacets().isEmpty())
808 {
809 clearTransientAndRemoveNonResetableComponents(context, ptc, child);
810 }
811 ptc.incrementCount();
812 }
813 else
814 {
815 root.getChildren().remove(i);
816 i--;
817 childCount--;
818 }
819 }
820 else
821 {
822 ptc.incrementCount();
823 }
824 }
825 else
826 {
827
828 root.getChildren().remove(i);
829 i--;
830 childCount--;
831 }
832 }
833 }
834 }
835
836 clearTransientAndNonFaceletComponentsForDynamicViewUIViewRootFacets(
837 context, root, viewStructureMetadata);
838 }
839 finally
840 {
841 root.getAttributes().put(ViewPoolProcessor.RESET_SAVE_STATE_MODE_KEY,
842 ViewPoolProcessor.RESET_MODE_OFF);
843 }
844 }
845
846 private void clearTransientAndRemoveNonResetableComponents(final FacesContext context,
847 final ClearPartialTreeContext ptc, final UIComponent component)
848 {
849
850 int childCount = component.getChildCount();
851 if (childCount > 0)
852 {
853 for (int i = 0; i < childCount; i++)
854 {
855 UIComponent child = component.getChildren().get(i);
856 boolean containsFaceletId = child.getAttributes().containsKey(ComponentSupport.MARK_CREATED);
857 if (child != null && child.isTransient() && !containsFaceletId)
858 {
859
860 component.getChildren().remove(i);
861 i--;
862 childCount--;
863 }
864 else
865 {
866 if (child.getAttributes().containsKey(ComponentSupport.COMPONENT_ADDED_BY_HANDLER_MARKER))
867 {
868
869 component.getChildren().remove(i);
870 i--;
871 childCount--;
872
873 }
874 else if (containsFaceletId ||
875 child.getAttributes().containsKey(ComponentSupport.COMPONENT_ADDED_BY_HANDLER_MARKER))
876 {
877
878
879
880 if (!child.isTransient())
881 {
882
883 Object state = child.saveState(context);
884 if (state == null)
885 {
886 if (child.getChildCount() > 0 || !child.getFacets().isEmpty())
887 {
888 clearTransientAndRemoveNonResetableComponents(context, ptc, child);
889 }
890 ptc.incrementCount();
891 }
892 else
893 {
894 component.getChildren().remove(i);
895 i--;
896 childCount--;
897 }
898 }
899 else
900 {
901 ptc.incrementCount();
902 }
903 }
904 else
905 {
906
907 component.getChildren().remove(i);
908 i--;
909 childCount--;
910 }
911 }
912 }
913 }
914
915
916 if (component.getFacetCount() > 0)
917 {
918 Map<String, UIComponent> facets = component.getFacets();
919 for (Iterator<UIComponent> itr = facets.values().iterator(); itr.hasNext();)
920 {
921 UIComponent fc = itr.next();
922 boolean containsFaceletId = fc.getAttributes().containsKey(ComponentSupport.MARK_CREATED);
923 if (fc != null && fc.isTransient() && !containsFaceletId)
924 {
925
926 itr.remove();
927 }
928 else
929 {
930 if (fc.getAttributes().containsKey(ComponentSupport.COMPONENT_ADDED_BY_HANDLER_MARKER))
931 {
932
933 itr.remove();
934
935 }
936 else if (containsFaceletId ||
937 fc.getAttributes().containsKey(ComponentSupport.COMPONENT_ADDED_BY_HANDLER_MARKER))
938 {
939
940
941
942 if (!fc.isTransient())
943 {
944
945 Object state = fc.saveState(context);
946 if (state == null)
947 {
948 if (fc.getChildCount() > 0 || !fc.getFacets().isEmpty())
949 {
950 clearTransientAndRemoveNonResetableComponents(context, ptc, fc);
951 }
952 ptc.incrementCount();
953 }
954 else
955 {
956 itr.remove();
957 }
958 }
959 else
960 {
961 ptc.incrementCount();
962 }
963 }
964 else
965 {
966
967 itr.remove();
968 }
969 }
970 }
971 }
972 }
973
974 public void processDeferredNavigation(FacesContext facesContext)
975 {
976 Object[] command = (Object[]) facesContext.getAttributes().get(
977 ViewPoolProcessor.INVOKE_DEFERRED_NAVIGATION);
978 if (command != null)
979 {
980 try
981 {
982 facesContext.getAttributes().put(ViewPoolProcessor.DISPOSE_VIEW_NAVIGATION, Boolean.TRUE);
983 NavigationHandler navigationHandler = facesContext.getApplication().getNavigationHandler();
984 if (command.length == 3)
985 {
986 navigationHandler.handleNavigation(facesContext, (String) command[0], (String) command[1],
987 (String) command[2]);
988 }
989 else
990 {
991 navigationHandler.handleNavigation(facesContext, (String) command[0], (String) command[1]);
992 }
993
994 facesContext.renderResponse();
995 facesContext.getAttributes().remove(ViewPoolProcessor.INVOKE_DEFERRED_NAVIGATION);
996 }
997 finally
998 {
999 facesContext.getAttributes().remove(ViewPoolProcessor.DISPOSE_VIEW_NAVIGATION);
1000 }
1001 }
1002 }
1003
1004 private static final String SERIALIZED_VIEW_REQUEST_ATTR =
1005 StateManagerImpl.class.getName() + ".SERIALIZED_VIEW";
1006
1007 public void disposeView(FacesContext facesContext, UIViewRoot root)
1008 {
1009 if (root == null)
1010 {
1011 return;
1012 }
1013
1014 String viewId = root.getViewId();
1015 if (viewId == null)
1016 {
1017 return;
1018 }
1019 Application app = facesContext.getApplication();
1020 if (app == null)
1021 {
1022 return;
1023 }
1024 ViewHandler viewHandler = app.getViewHandler();
1025 if (viewHandler == null)
1026 {
1027 return;
1028 }
1029
1030 if (Boolean.TRUE.equals(facesContext.getAttributes().get(ViewPoolProcessor.DISPOSE_VIEW_NAVIGATION)))
1031 {
1032 ViewDeclarationLanguage vdl = facesContext.getApplication().
1033 getViewHandler().getViewDeclarationLanguage(
1034 facesContext, root.getViewId());
1035
1036 if (vdl != null && ViewDeclarationLanguage.FACELETS_VIEW_DECLARATION_LANGUAGE_ID.equals(vdl.getId()))
1037 {
1038 StateManagementStrategy sms = vdl.getStateManagementStrategy(facesContext, root.getId());
1039 if (sms != null)
1040 {
1041
1042 facesContext.getAttributes().put(ViewPoolProcessor.FORCE_HARD_RESET, Boolean.TRUE);
1043
1044 try
1045 {
1046 Object state = sms.saveView(facesContext);
1047 }
1048 finally
1049 {
1050 facesContext.getAttributes().remove(ViewPoolProcessor.FORCE_HARD_RESET);
1051 }
1052
1053
1054 facesContext.getAttributes().remove(SERIALIZED_VIEW_REQUEST_ATTR);
1055 }
1056 }
1057 }
1058 }
1059
1060 private static class ClearPartialTreeContext
1061 {
1062 private int count;
1063
1064 public ClearPartialTreeContext()
1065 {
1066 count = 0;
1067 }
1068
1069
1070
1071
1072 public int getCount()
1073 {
1074 return count;
1075 }
1076
1077 public int incrementCount()
1078 {
1079 return count++;
1080 }
1081
1082
1083
1084 public void setCount(int count)
1085 {
1086 this.count = count;
1087 }
1088 }
1089 }