You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2013/12/13 02:18:10 UTC

svn commit: r1550609 [2/5] - in /myfaces/core/trunk: api/src/main/java/javax/faces/component/ api/src/test/java/javax/faces/component/ impl/src/main/java/org/apache/myfaces/application/ impl/src/main/java/org/apache/myfaces/config/ impl/src/main/java/o...

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementStrategy.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementStrategy.java?rev=1550609&r1=1550608&r2=1550609&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementStrategy.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementStrategy.java Fri Dec 13 01:18:08 2013
@@ -61,7 +61,11 @@ import org.apache.myfaces.shared.util.Cl
 import org.apache.myfaces.shared.util.HashMapUtils;
 import org.apache.myfaces.shared.util.WebConfigParamUtils;
 import org.apache.myfaces.view.facelets.compiler.CheckDuplicateIdFaceletUtils;
+import org.apache.myfaces.view.facelets.pool.ViewEntry;
+import org.apache.myfaces.view.facelets.pool.ViewPool;
+import org.apache.myfaces.view.facelets.pool.ViewStructureMetadata;
 import org.apache.myfaces.view.facelets.tag.jsf.ComponentSupport;
+import org.apache.myfaces.view.facelets.tag.jsf.FaceletState;
 
 /**
  * This class implements partial state saving feature when facelets
@@ -181,10 +185,21 @@ public class DefaultFaceletsStateManagem
     
     private String _checkIdsProductionMode;
     
+    private MyfacesConfig _config;
+    
+    private ViewPoolProcessor _viewPoolProcessor;
+    
     public DefaultFaceletsStateManagementStrategy ()
     {
+        this(FacesContext.getCurrentInstance());
+    }
+    
+    public DefaultFaceletsStateManagementStrategy (FacesContext context)
+    {
         _vdlFactory = (ViewDeclarationLanguageFactory)
                 FactoryFinder.getFactory(FactoryFinder.VIEW_DECLARATION_LANGUAGE_FACTORY);
+        _config = MyfacesConfig.getCurrentInstance(context.getExternalContext());
+        _viewPoolProcessor = ViewPoolProcessor.getInstance(context);
     }
     
     @SuppressWarnings("unchecked")
@@ -258,7 +273,7 @@ public class DefaultFaceletsStateManagem
                 }
                 
                 context.setViewRoot (view); 
-                
+                boolean skipBuildView = false;
                 if (state != null && state[1] != null)
                 {
                     // Since JSF 2.2, UIViewRoot.restoreViewScopeState() must be called, but
@@ -266,13 +281,32 @@ public class DefaultFaceletsStateManagem
                     // id from this location. Remember in this point, PSS is enabled, so the
                     // code match with the assigment done in 
                     // FaceletViewDeclarationLanguage.buildView()
+                    states = (Map<String, Object>) state[1];
+                    faceletViewState = UIComponentBase.restoreAttachedState(
+                            context,states.get(ComponentSupport.FACELET_STATE_INSTANCE));
+                    if (faceletViewState != null && _viewPoolProcessor != null)
+                    {
+                        ViewPool viewPool = _viewPoolProcessor.getViewPool(context, view);
+                        if (viewPool != null)
+                        {
+                            ViewStructureMetadata viewMetadata = viewPool.retrieveDynamicViewStructureMetadata(
+                                context, view, (FaceletState) faceletViewState);
+                            if (viewMetadata != null)
+                            {
+                                ViewEntry entry = viewPool.popDynamicStructureView(context, view,
+                                        (FaceletState) faceletViewState);
+                                if (entry != null)
+                                {
+                                    skipBuildView = true;
+                                    _viewPoolProcessor.cloneAndRestoreView(context, view, entry, viewMetadata);
+                                }
+                            }
+                        }
+                    }
                     if (view.getId() == null)
                     {
                         view.setId(view.createUniqueId(context, null));
                     }
-                    states = (Map<String, Object>) state[1];
-                    faceletViewState = UIComponentBase.restoreAttachedState(
-                            context,states.get(ComponentSupport.FACELET_STATE_INSTANCE));
                     if (faceletViewState != null)
                     {
                         view.getAttributes().put(ComponentSupport.FACELET_STATE_INSTANCE,  faceletViewState);
@@ -300,18 +334,21 @@ public class DefaultFaceletsStateManagem
                 // and then to true when postback. Since we need listeners registered to PostAddToViewEvent
                 // event to be handled, we should enable it again. For partial state saving we need this listeners
                 // be called from here and relocate components properly.
-                try 
-                {
-                    context.setProcessingEvents (true);
-                    vdl.buildView (context, view);
-                    // In the latest code related to PostAddToView, it is
-                    // triggered no matter if it is applied on postback. It seems that MYFACES-2389, 
-                    // TRINIDAD-1670 and TRINIDAD-1671 are related.
-                    suscribeListeners(view);
-                }
-                finally
+                if (!skipBuildView)
                 {
-                    context.setProcessingEvents (oldContextEventState);
+                    try 
+                    {
+                        context.setProcessingEvents (true);
+                        vdl.buildView (context, view);
+                        // In the latest code related to PostAddToView, it is
+                        // triggered no matter if it is applied on postback. It seems that MYFACES-2389, 
+                        // TRINIDAD-1670 and TRINIDAD-1671 are related.
+                        suscribeListeners(view);
+                    }
+                    finally
+                    {
+                        context.setProcessingEvents (oldContextEventState);
+                    }
                 }
             }
             catch (Throwable e)
@@ -583,7 +620,11 @@ public class DefaultFaceletsStateManagem
             
             // Create save state objects for every component.
             
-            if (view.getAttributes().containsKey(COMPONENT_ADDED_AFTER_BUILD_VIEW))
+            boolean viewResetable = false;
+            int count = 0;
+            Object faceletViewState = null;
+            boolean saveViewFully = view.getAttributes().containsKey(COMPONENT_ADDED_AFTER_BUILD_VIEW);
+            if (saveViewFully)
             {
                 ensureClearInitialState(view);
                 Object rlcStates = !context.getResourceLibraryContracts().isEmpty() ? 
@@ -597,7 +638,7 @@ public class DefaultFaceletsStateManagem
             {
                 states = new HashMap<String, Object>();
 
-                Object faceletViewState = view.getAttributes().get(ComponentSupport.FACELET_STATE_INSTANCE);
+                faceletViewState = view.getAttributes().get(ComponentSupport.FACELET_STATE_INSTANCE);
                 if (faceletViewState != null)
                 {
                     ((Map<String, Object>)states).put(ComponentSupport.FACELET_STATE_INSTANCE,
@@ -605,7 +646,20 @@ public class DefaultFaceletsStateManagem
                     //Do not save on UIViewRoot
                     view.getAttributes().remove(ComponentSupport.FACELET_STATE_INSTANCE);
                 }
-                saveStateOnMapVisitTree(context,(Map<String,Object>) states, view);
+                if (_viewPoolProcessor != null && 
+                    _viewPoolProcessor.isViewPoolEnabledForThisView(context, view))
+                {
+                    SaveStateAndResetViewCallback cb = saveStateOnMapVisitTreeAndReset(
+                            context,(Map<String,Object>) states, view,
+                            Boolean.TRUE.equals(
+                        context.getAttributes().get(ViewPoolProcessor.FORCE_HARD_RESET)));
+                    viewResetable = cb.isViewResetable();
+                    count = cb.getCount();
+                }
+                else
+                {
+                    saveStateOnMapVisitTree(context,(Map<String,Object>) states, view);
+                }
                 
                 if ( ((Map<String,Object>)states).isEmpty())
                 {
@@ -627,6 +681,21 @@ public class DefaultFaceletsStateManagem
                 serializedView = new Object[] { null, states };
             }
             
+            //If view cache enabled store the view state into the pool
+            if (!saveViewFully && _viewPoolProcessor != null)
+            {
+                if (viewResetable)
+                {
+                    _viewPoolProcessor.pushResetableView(
+                        context, view, (FaceletState) faceletViewState);
+                }
+                else
+                {
+                    _viewPoolProcessor.pushPartialView(
+                        context, view, (FaceletState) faceletViewState, count);
+                }
+            }
+            
             context.getAttributes().put(SERIALIZED_VIEW_REQUEST_ATTR, serializedView);
 
         }
@@ -911,6 +980,304 @@ public class DefaultFaceletsStateManagem
         }
     }
     
+    
+    private SaveStateAndResetViewCallback saveStateOnMapVisitTreeAndReset(final FacesContext facesContext,
+            final Map<String,Object> states, final UIViewRoot uiViewRoot, boolean forceHardReset)
+    {
+        facesContext.getAttributes().put(SKIP_ITERATION_HINT, Boolean.TRUE);
+        SaveStateAndResetViewCallback callback = new SaveStateAndResetViewCallback(
+                facesContext.getViewRoot(), states, forceHardReset);
+        if (forceHardReset)
+        {
+            uiViewRoot.getAttributes().put(ViewPoolProcessor.RESET_SAVE_STATE_MODE_KEY, 
+                    ViewPoolProcessor.RESET_MODE_HARD);
+        }
+        else
+        {
+            uiViewRoot.getAttributes().put(ViewPoolProcessor.RESET_SAVE_STATE_MODE_KEY, 
+                    ViewPoolProcessor.RESET_MODE_SOFT);
+        }
+        try
+        {
+            if (_viewPoolProcessor != null && 
+                !_viewPoolProcessor.isViewPoolEnabledForThisView(facesContext, uiViewRoot))
+            {
+                callback.setViewResetable(false);
+            }
+            
+            // Check if the view has removed components. If that so, it
+            // means there is some manipulation over the component tree that
+            // can be rollback, so it is ok to set the view as resetable.
+            if (callback.isViewResetable())
+            {
+                List<String> removedIds = getClientIdsRemoved(uiViewRoot);
+                if (removedIds != null && !removedIds.isEmpty())
+                {
+                    callback.setViewResetable(false);
+                }
+            }
+
+            try
+            {
+                uiViewRoot.visitTree( getVisitContextFactory().getVisitContext(
+                        facesContext, null, VISIT_HINTS), callback);
+            }
+            finally
+            {
+                facesContext.getAttributes().remove(SKIP_ITERATION_HINT);
+            }
+            
+            if (callback.isViewResetable() && callback.isRemoveAddedComponents())
+            {
+                List<String> clientIdsToRemove = getClientIdsAdded(uiViewRoot);
+
+                if (clientIdsToRemove != null)
+                {
+                    // perf: clientIds are ArrayList: see method registerOnAddRemoveList(String)
+                    for (int i = 0, size = clientIdsToRemove.size(); i < size; i++)
+                    {
+                        String clientId = clientIdsToRemove.get(i);
+                        uiViewRoot.invokeOnComponent(facesContext, clientId, new RemoveComponentCallback());
+                    }
+                }
+            }
+
+            Object state = uiViewRoot.saveState (facesContext);
+            if (state != null)
+            {
+                // Save by client ID into our map.
+                states.put (uiViewRoot.getClientId (facesContext), state);
+
+                //Hard reset (or reset and check state again)
+                Integer oldResetMode = (Integer) uiViewRoot.getAttributes().put(
+                        ViewPoolProcessor.RESET_SAVE_STATE_MODE_KEY, ViewPoolProcessor.RESET_MODE_HARD);
+                state = uiViewRoot.saveState (facesContext);
+                uiViewRoot.getAttributes().put(ViewPoolProcessor.RESET_SAVE_STATE_MODE_KEY, oldResetMode);
+                if (state != null)
+                {
+                    callback.setViewResetable(false);
+                }
+            }
+        }
+        finally
+        {
+            uiViewRoot.getAttributes().put(ViewPoolProcessor.RESET_SAVE_STATE_MODE_KEY, 
+                    ViewPoolProcessor.RESET_MODE_OFF);
+        }
+        return callback;
+    }
+    
+    private class SaveStateAndResetViewCallback implements VisitCallback
+    {
+        private final Map<String, Object> states;
+        
+        private final UIViewRoot view;
+        
+        private boolean viewResetable;
+        
+        private boolean skipRoot;
+        
+        private int count;
+        
+        private boolean forceHardReset;
+        
+        private boolean removeAddedComponents;
+        
+        public SaveStateAndResetViewCallback(UIViewRoot view, Map<String, Object> states,
+                boolean forceHardReset)
+        {
+            this.states = states;
+            this.view = view;
+            this.viewResetable = true;
+            this.skipRoot = true;
+            this.count = 0;
+            this.forceHardReset = forceHardReset;
+            this.removeAddedComponents = false;
+        }
+        
+        public VisitResult visit(VisitContext context, UIComponent target)
+        {
+            FacesContext facesContext = context.getFacesContext();
+            Object state;
+            this.count++;
+
+            if ((target == null) || target.isTransient())
+            {
+                // No need to bother with these components or their children.
+
+                return VisitResult.REJECT;
+            }
+            
+            if (skipRoot && target instanceof UIViewRoot)
+            {
+                //UIViewRoot should be scanned at last.
+                skipRoot = false;
+                return VisitResult.ACCEPT;
+            }
+
+            ComponentState componentAddedAfterBuildView
+                    = (ComponentState) target.getAttributes().get(COMPONENT_ADDED_AFTER_BUILD_VIEW);
+
+            //Note if UIViewRoot has this marker, JSF 1.2 like state saving is used.
+            if (componentAddedAfterBuildView != null && (target.getParent() != null))
+            {
+                //Set this view as not resetable.
+                //setViewResetable(false);
+                // Enable flag to remove added components later
+                setRemoveAddedComponents(true);
+                if (forceHardReset)
+                {
+                    // The ideal is remove the added component here but visitTree does not support that
+                    // kind of tree manipulation.
+                    if (isViewResetable() &&
+                        ComponentState.REMOVE_ADD.equals(componentAddedAfterBuildView))
+                    {
+                        setViewResetable(false);
+                    }
+                    // it is not important to save anything, skip
+                    return VisitResult.REJECT;
+                }
+                if (ComponentState.REMOVE_ADD.equals(componentAddedAfterBuildView))
+                {
+                    //If the view has removed components, set the view as non resetable
+                    setViewResetable(false);
+                    registerOnAddRemoveList(facesContext, target.getClientId(facesContext));
+                    target.getAttributes().put(COMPONENT_ADDED_AFTER_BUILD_VIEW, ComponentState.ADDED);
+                }
+                else if (ComponentState.ADD.equals(componentAddedAfterBuildView))
+                {
+                    registerOnAddList(facesContext, target.getClientId(facesContext));
+                    target.getAttributes().put(COMPONENT_ADDED_AFTER_BUILD_VIEW, ComponentState.ADDED);
+                }
+                else if (ComponentState.ADDED.equals(componentAddedAfterBuildView))
+                {
+                    // Later on the check of removed components we'll see if the view
+                    // is resetable or not.
+                    registerOnAddList(facesContext, target.getClientId(facesContext));
+                }
+                ensureClearInitialState(target);
+                //Save all required info to restore the subtree.
+                //This includes position, structure and state of subtree
+
+                int childIndex = target.getParent().getChildren().indexOf(target);
+                if (childIndex >= 0)
+                {
+                    states.put(target.getClientId(facesContext), new AttachedFullStateWrapper( 
+                            new Object[]{
+                                target.getParent().getClientId(facesContext),
+                                null,
+                                childIndex,
+                                internalBuildTreeStructureToSave(target),
+                                target.processSaveState(facesContext)}));
+                }
+                else
+                {
+                    String facetName = null;
+                    if (target.getParent().getFacetCount() > 0)
+                    {
+                        for (Map.Entry<String, UIComponent> entry : target.getParent().getFacets().entrySet()) 
+                        {
+                            if (target.equals(entry.getValue()))
+                            {
+                                facetName = entry.getKey();
+                                break;
+                            }
+                        }
+                    }
+                    states.put(target.getClientId(facesContext),new AttachedFullStateWrapper(new Object[]{
+                            target.getParent().getClientId(facesContext),
+                            facetName,
+                            null,
+                            internalBuildTreeStructureToSave(target),
+                            target.processSaveState(facesContext)}));
+                }
+                return VisitResult.REJECT;
+            }
+            else if (target.getParent() != null)
+            {
+                if (forceHardReset)
+                {
+                    // force hard reset set reset move on top
+                    state = target.saveState (facesContext);
+                    if (state != null)
+                    {
+                        setViewResetable(false);
+                        return VisitResult.REJECT;
+                    }
+                }
+                else
+                {
+                    state = target.saveState (facesContext);
+
+                    if (state != null)
+                    {
+                        // Save by client ID into our map.
+                        states.put (target.getClientId (facesContext), state);
+
+                        if (isViewResetable())
+                        {
+                            //Hard reset (or reset and check state again)
+                            Integer oldResetMode = (Integer) view.getAttributes().put(
+                                    ViewPoolProcessor.RESET_SAVE_STATE_MODE_KEY, 
+                                    ViewPoolProcessor.RESET_MODE_HARD);
+                            state = target.saveState (facesContext);
+                            view.getAttributes().put(ViewPoolProcessor.RESET_SAVE_STATE_MODE_KEY, 
+                                    oldResetMode);
+                            if (state != null)
+                            {
+                                setViewResetable(false);
+                            }
+                        }
+                    }
+                }
+
+                return VisitResult.ACCEPT;
+            }
+            else
+            {
+                //Only UIViewRoot has no parent in a component tree.
+                return VisitResult.ACCEPT;
+            }
+        }
+        
+        /**
+         * @return the viewResetable
+         */
+        public boolean isViewResetable()
+        {
+            return viewResetable;
+        }
+
+        /**
+         * @param viewResetable the viewResetable to set
+         */
+        public void setViewResetable(boolean viewResetable)
+        {
+            this.viewResetable = viewResetable;
+        }
+        
+        public int getCount()
+        {
+            return count;
+        }
+
+        /**
+         * @return the removeAddedComponents
+         */
+        public boolean isRemoveAddedComponents()
+        {
+            return removeAddedComponents;
+        }
+
+        /**
+         * @param removeAddedComponents the removeAddedComponents to set
+         */
+        public void setRemoveAddedComponents(boolean removeAddedComponents)
+        {
+            this.removeAddedComponents = removeAddedComponents;
+        }
+    }
+    
     protected void ensureClearInitialState(UIComponent c)
     {
         c.clearInitialState();

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java?rev=1550609&r1=1550608&r2=1550609&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java Fri Dec 13 01:18:08 2013
@@ -90,6 +90,7 @@ import javax.faces.view.facelets.Facelet
 import javax.faces.view.facelets.FaceletContext;
 import javax.faces.view.facelets.ResourceResolver;
 import javax.servlet.http.HttpServletResponse;
+import org.apache.myfaces.application.StateManagerImpl;
 
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
 import org.apache.myfaces.config.RuntimeConfig;
@@ -125,6 +126,10 @@ import static org.apache.myfaces.view.fa
 import org.apache.myfaces.view.facelets.compiler.FaceletsCompilerSupport;
 import org.apache.myfaces.view.facelets.compiler.RefreshDynamicComponentListener;
 import org.apache.myfaces.view.facelets.impl.SectionUniqueIdCounter;
+import org.apache.myfaces.view.facelets.pool.RestoreViewFromPoolResult;
+import org.apache.myfaces.view.facelets.pool.ViewEntry;
+import org.apache.myfaces.view.facelets.pool.ViewPool;
+import org.apache.myfaces.view.facelets.pool.ViewStructureMetadata;
 import org.apache.myfaces.view.facelets.tag.composite.CreateDynamicCompositeComponentListener;
 import org.apache.myfaces.view.facelets.tag.jsf.PartialMethodExpressionActionListener;
 import org.apache.myfaces.view.facelets.tag.jsf.PartialMethodExpressionValidator;
@@ -283,18 +288,24 @@ public class FaceletViewDeclarationLangu
     private List<String> _prefixWildcardKeys;
     
     private FaceletsCompilerSupport _faceletsCompilerSupport;
+    
+    private MyfacesConfig _config;
+    
+    private ViewPoolProcessor _viewPoolProcessor;
 
     /**
      *
      */
     public FaceletViewDeclarationLanguage(FacesContext context)
     {
+        _config = MyfacesConfig.getCurrentInstance(context.getExternalContext());
         initialize(context);
         _strategy = new FaceletViewDeclarationLanguageStrategy();
     }
 
     public FaceletViewDeclarationLanguage(FacesContext context, ViewDeclarationLanguageStrategy strategy)
     {
+        _config = MyfacesConfig.getCurrentInstance(context.getExternalContext());
         initialize(context);
         _strategy = strategy;
     }
@@ -316,6 +327,28 @@ public class FaceletViewDeclarationLangu
         return false;
     }
 
+    private RestoreViewFromPoolResult tryRestoreViewFromCache(FacesContext context, UIViewRoot view)
+    {
+        if (_viewPoolProcessor != null)
+        {
+            ViewPool viewPool = _viewPoolProcessor.getViewPool(context, view);
+            if (viewPool != null)
+            {
+                ViewStructureMetadata metadata = viewPool.retrieveStaticViewStructureMetadata(context, view);
+                if (metadata != null)
+                {
+                    ViewEntry entry = viewPool.popStaticOrPartialStructureView(context, view);
+                    if (entry != null)
+                    {
+                        _viewPoolProcessor.cloneAndRestoreView(context, view, entry, metadata);
+                        return entry.getResult();
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
     /**
      * {@inheritDoc}
      */
@@ -356,7 +389,48 @@ public class FaceletViewDeclarationLangu
         boolean usePartialStateSavingOnThisView = _usePartialStateSavingOnThisView(renderedViewId);
         boolean refreshTransientBuild = (view.getChildCount() > 0);
         boolean refreshTransientBuildOnPSS = (usePartialStateSavingOnThisView && _refreshTransientBuildOnPSS);
+        boolean refreshPartialView = false;
 
+        if (_viewPoolProcessor != null && !refreshTransientBuild)
+        {
+            RestoreViewFromPoolResult result = tryRestoreViewFromCache(context, view);
+            if (result != null)
+            {
+                // Since all transient stuff has been removed, add listeners that keep
+                // track of tree updates.
+                if (RestoreViewFromPoolResult.COMPLETE.equals(result))
+                {
+                    if (!PhaseId.RESTORE_VIEW.equals(context.getCurrentPhaseId()))
+                    {
+                        ((DefaultFaceletsStateManagementStrategy) 
+                                getStateManagementStrategy(context, view.getViewId())).
+                                suscribeListeners(view);
+                    }
+                    // If the result is complete, the view restored here is static. 
+                    // static views can be marked as filled.
+                    if (!refreshTransientBuildOnPSS)
+                    {
+                        // This option will be true on this cases:
+                        // -pss is true and refresh is not active
+                        setFilledView(context, view);
+                    }
+                    //At this point refreshTransientBuild = false && refreshTransientBuildOnPSS is true
+                    else if (_refreshTransientBuildOnPSSAuto &&
+                             !context.getAttributes().containsKey(CLEAN_TRANSIENT_BUILD_ON_RESTORE))
+                    {
+                        setFilledView(context, view);
+                    }
+                    return;
+                }
+                else
+                {
+                    // We need to refresh a partial view.
+                    refreshTransientBuild = true;
+                    refreshPartialView = true;
+                }
+            }
+        }
+        
         if (usePartialStateSavingOnThisView)
         {
             // Before apply we need to make sure the current view has
@@ -371,7 +445,7 @@ public class FaceletViewDeclarationLangu
             context.getAttributes().put(USING_PSS_ON_THIS_VIEW, Boolean.TRUE);
             //Add a key to indicate ComponentTagHandlerDelegate to 
             //call UIComponent.markInitialState after it is populated
-            if (!refreshTransientBuild)
+            if (!refreshTransientBuild || refreshPartialView)
             {
                 context.getAttributes().put(StateManager.IS_BUILDING_INITIAL_STATE, Boolean.TRUE);
                 context.getAttributes().put(IS_BUILDING_INITIAL_STATE_KEY_ALIAS, Boolean.TRUE);
@@ -466,8 +540,14 @@ public class FaceletViewDeclarationLangu
             // UIViewRoot.markInitialState() is not called because it does
             // not have a facelet tag handler class that create it, instead
             // new instances are created programatically.
-            if (!refreshTransientBuild)
+            if (!refreshTransientBuild || refreshPartialView)
             {
+                // Save the state
+                if (_viewPoolProcessor != null &&
+                    _viewPoolProcessor.isViewPoolEnabledForThisView(context, view))
+                {
+                    _viewPoolProcessor.storeViewStructureMetadata(context, view);
+                }
                 if (_markInitialStateWhenApplyBuildView)
                 {
                     if (!refreshTransientBuildOnPSS ||
@@ -1727,7 +1807,7 @@ public class FaceletViewDeclarationLangu
         // the current view is not on javax.faces.FULL_STATE_SAVING_VIEW_IDS.
         if (_partialStateSaving && _stateMgmtStrategy == null)
         {
-            _stateMgmtStrategy = new DefaultFaceletsStateManagementStrategy();
+            _stateMgmtStrategy = new DefaultFaceletsStateManagementStrategy(context);
         }
 
         return _usePartialStateSavingOnThisView(viewId) ? _stateMgmtStrategy : null;
@@ -1881,6 +1961,42 @@ public class FaceletViewDeclarationLangu
                         // saved yet.
                         stateMgr.saveView(context);
                     }
+                    else
+                    {
+                        // GET case without any form that trigger state saving.
+                        // Try to store it into cache.
+                        if (_viewPoolProcessor != null && 
+                            _viewPoolProcessor.isViewPoolEnabledForThisView(context, view))
+                        {
+                            ViewDeclarationLanguage vdl = context.getApplication().
+                                    getViewHandler().getViewDeclarationLanguage(
+                                        context, view.getViewId());
+
+                            if (ViewDeclarationLanguage.FACELETS_VIEW_DECLARATION_LANGUAGE_ID.equals(
+                                    vdl.getId()))
+                            {
+                                StateManagementStrategy sms = vdl.getStateManagementStrategy(
+                                        context, view.getId());
+                                if (sms != null)
+                                {
+                                    context.getAttributes().put(ViewPoolProcessor.FORCE_HARD_RESET, Boolean.TRUE);
+
+                                    // Force indirectly to store the map in the cache
+                                    try
+                                    {
+                                        Object state = sms.saveView(context);
+                                    }
+                                    finally
+                                    {
+                                        context.getAttributes().remove(ViewPoolProcessor.FORCE_HARD_RESET);
+                                    }
+
+                                    // Clear the calculated value from the application map
+                                    context.getAttributes().remove(SERIALIZED_VIEW_REQUEST_ATTR);
+                                }
+                            }
+                        }
+                    }
                 }
                 finally
                 {
@@ -1902,6 +2018,9 @@ public class FaceletViewDeclarationLangu
             handleRenderException(context, e);
         }
     }
+    
+    private static final String SERIALIZED_VIEW_REQUEST_ATTR = 
+        StateManagerImpl.class.getName() + ".SERIALIZED_VIEW";
 
     /**
      * {@inheritDoc}
@@ -2355,6 +2474,8 @@ public class FaceletViewDeclarationLangu
             eContext.getApplicationMap().put(
                     CACHED_COMPONENT_IDS, componentIdsCached);
         }
+        
+        _viewPoolProcessor = ViewPoolProcessor.getInstance(context);
 
         log.finest("Initialization Successful");
     }

Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/ViewPoolProcessor.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/ViewPoolProcessor.java?rev=1550609&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/ViewPoolProcessor.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/ViewPoolProcessor.java Fri Dec 13 01:18:08 2013
@@ -0,0 +1,1008 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.view.facelets;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.faces.application.Application;
+import javax.faces.application.NavigationHandler;
+import javax.faces.application.ProjectStage;
+import javax.faces.application.ResourceDependency;
+import javax.faces.application.ViewHandler;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseId;
+import javax.faces.view.StateManagementStrategy;
+import javax.faces.view.ViewDeclarationLanguage;
+import org.apache.myfaces.application.StateManagerImpl;
+import org.apache.myfaces.component.ComponentResourceContainer;
+import org.apache.myfaces.context.RequestViewContext;
+import org.apache.myfaces.context.RequestViewMetadata;
+import org.apache.myfaces.lifecycle.DefaultRestoreViewSupport;
+import org.apache.myfaces.lifecycle.RestoreViewSupport;
+import org.apache.myfaces.shared.util.WebConfigParamUtils;
+import org.apache.myfaces.view.facelets.impl.FaceletCompositionContextImpl;
+import org.apache.myfaces.view.facelets.pool.ViewPool;
+import org.apache.myfaces.view.facelets.pool.ViewPoolFactory;
+import org.apache.myfaces.view.facelets.pool.ViewEntry;
+import org.apache.myfaces.view.facelets.pool.ViewStructureMetadata;
+import org.apache.myfaces.view.facelets.pool.impl.ViewPoolFactoryImpl;
+import org.apache.myfaces.view.facelets.tag.jsf.ComponentSupport;
+import org.apache.myfaces.view.facelets.tag.jsf.FaceletState;
+
+/**
+ * This class is reponsible for all processing tasks related to the view pool.
+ * 
+ * For enable the pool only for a subset of your views, you can
+ * add an entry inside faces-config.xml file like this:
+ * <pre>
+ * {@code 
+ * <faces-config-extension>
+ *   <view-pool-mapping>
+ *      <url-pattern>/*</url-pattern>
+ *      <parameter>
+ *          <name>org.apache.myfaces.VIEW_POOL_MAX_POOL_SIZE</name>
+ *          <value>5</value>
+ *      </parameter>
+ *  </view-pool-mapping>
+ * </faces-config-extension>
+ * }
+ * </pre>
+ * 
+ * @author Leonardo Uribe
+ */
+public class ViewPoolProcessor
+{
+    /**
+     * Used to hold the view pool processor instance on the application map. 
+     * A ViewPoolProcessor is only accessible if the view pool has been
+     * enabled for the whole application (using a web config parameter) or 
+     * partially (an &lt;view-pool-mapping&gt; entry inside &lt;faces-config-extension&gt;).
+     */
+    private final static String INSTANCE = "oam.ViewPoolProcessor";
+    
+    /**
+     * UIViewRoot attribute to enable/disable the view for use pooling.
+     */
+    public final static String ENABLE_VIEW_POOL = "oamEnableViewPool";
+    
+    /**
+     * Flag that indicates to the StateManagementStrategy that no state needs 
+     * to be stored and we are using saveState() to dispose the view and store it
+     * into the pool directly.
+     */
+    public final static String FORCE_HARD_RESET = "oam.ViewPool.forceHardReset";
+    
+    /**
+     * Flag to indicate that dispose this view on navigation is valid.
+     */
+    public final static String DISPOSE_VIEW_NAVIGATION = "oam.ViewPool.disposeViewOnNavigation";
+    
+    /**
+     * Attribute of UIViewRoot that indicates if a soft (1) or hard(2) 
+     * (reset and check) reset is required in the call to saveState().
+     */
+    public final static String RESET_SAVE_STATE_MODE_KEY ="oam.view.resetSaveStateMode";
+    
+    /**
+     * Indicates no reset should be done on this state saving
+     */
+    public static final int RESET_MODE_OFF = 0;
+    
+    /**
+     * Indicates a soft reset should be done when saveState(...) is performed,
+     * which means all transient state should be cleared but the delta state 
+     * should not be destroyed in the process.
+     */
+    public static final int RESET_MODE_SOFT = 1;
+    
+    /**
+     * Indicates a hard reset should be done when saveState(...) is performed,
+     * which means all transient and delta state should be cleared, destroying
+     * all existing state in the process. If something cannot be reseted, the 
+     * state should return non null, so the algorithm can remove the component
+     * from the tree and mark the tree as partial (requires refresh before
+     * reuse).
+     */
+    public static final int RESET_MODE_HARD = 2;
+    
+    /**
+     * Param used to indicate a "deferred navigation" needs to be done. To allow the view pool to
+     * dispose the view properly (and reuse it later), it is necessary to ensure the view is not
+     * being used at the moment. If the navigation call occur inside an action listener, the current
+     * view is being used and cannot be disposed (because it conflicts with hard/soft reset). This
+     * extension allows to call handleNavigation() before end invoke application phase, but after
+     * traverse the component tree. 
+     */
+    public static final String INVOKE_DEFERRED_NAVIGATION = "oam.invoke.navigation";
+
+    private ViewPoolFactory viewPoolFactory;
+    private RestoreViewSupport restoreViewSupport;
+    
+    public ViewPoolProcessor(FacesContext context)
+    {
+        viewPoolFactory = new ViewPoolFactoryImpl(context);
+        restoreViewSupport = new DefaultRestoreViewSupport(context);
+    }
+    
+    public static ViewPoolProcessor getInstance(FacesContext context)
+    {
+        return (ViewPoolProcessor) context.getExternalContext().
+                getApplicationMap().get(INSTANCE);
+    }
+    
+    /**
+     * This method should be called at startup to decide if a view processor should be
+     * provided or not to the runtime.
+     * 
+     * @param context 
+     */
+    public static void initialize(FacesContext context)
+    {
+        if (context.isProjectStage(ProjectStage.Production))
+        {
+            String elMode = WebConfigParamUtils.getStringInitParameter(
+                        context.getExternalContext(),
+                        FaceletCompositionContextImpl.INIT_PARAM_CACHE_EL_EXPRESSIONS, 
+                            ELExpressionCacheMode.noCache.name());
+            if (elMode.equals(ELExpressionCacheMode.alwaysRecompile.name()))
+            {
+                ViewPoolProcessor processor = new ViewPoolProcessor(context);
+                context.getExternalContext().
+                    getApplicationMap().put(INSTANCE, processor);
+            }
+            else
+            {
+                Logger.getLogger(ViewPoolProcessor.class.getName()).log(
+                    Level.INFO, FaceletCompositionContextImpl.INIT_PARAM_CACHE_EL_EXPRESSIONS +
+                    " web config parameter is set to \"" + ( (elMode == null) ? "none" : elMode) +
+                    "\". To enable view pooling this param"+
+                    " must be set to \"alwaysRecompile\". View Pooling disabled.");
+            }
+        }
+    }
+
+    public ViewPool getViewPool(FacesContext context, UIViewRoot root)
+    {
+        if (root.isTransient())
+        {
+            // Stateless views cannot be pooled, because we are reusing
+            // state saving algorithm for that.
+            return null;
+        }
+        Boolean enableViewPool = (Boolean) root.getAttributes().get(ViewPoolProcessor.ENABLE_VIEW_POOL);
+        if (enableViewPool != null && !Boolean.TRUE.equals(enableViewPool))
+        {
+            // view pool not enabled for this view.
+            return null;
+        }
+        else
+        {
+            return viewPoolFactory.getViewPool(context, root);
+        }
+    }
+    
+    public boolean isViewPoolEnabledForThisView(FacesContext context, UIViewRoot root)
+    {
+        if (root.isTransient())
+        {
+            // Stateless views cannot be pooled, because we are reusing
+            // state saving algorithm for that.
+            return false;
+        }
+        Boolean enableViewPool = (Boolean) root.getAttributes().get(ViewPoolProcessor.ENABLE_VIEW_POOL);
+        if (enableViewPool != null)
+        {
+            if (Boolean.TRUE.equals(enableViewPool))
+            {
+                return true;
+            }
+            else
+            {
+                return false;
+            }
+        }
+        else
+        {
+            ViewPool viewPool = getViewPool(context, root);
+            if (viewPool != null)
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean isViewPoolStrategyAllowedForThisView(FacesContext context, UIViewRoot root)
+    {
+        // Check if the viewId is not null.
+        if (root.getViewId() == null)
+        {
+            return false;
+        }
+        if (root.isTransient())
+        {
+            // Stateless views cannot be pooled, because we are reusing
+            // state saving algorithm for that.
+            return false;
+        }
+        
+        // Check if the view is enabled or not for use pooling
+        if (!isViewPoolEnabledForThisView(context, root))
+        {
+            return false;
+        }
+
+        // Check if the vdl is using PSS on this view (has a vdl and that vdl is facelets)
+        ViewDeclarationLanguage vdl = context.getApplication().getViewHandler().
+            getViewDeclarationLanguage(context, root.getViewId());
+        if (vdl == null)
+        {
+            return false;
+        }
+        else if (!ViewDeclarationLanguage.FACELETS_VIEW_DECLARATION_LANGUAGE_ID.equals(vdl.getId()))
+        {
+            return false;
+        }
+        
+        if (vdl.getStateManagementStrategy(context, root.getViewId()) == null)
+        {
+            return false;
+        }
+        return true;
+    }
+
+    public void setViewPoolDisabledOnThisView(FacesContext context, UIViewRoot root, boolean value)
+    {
+        root.getAttributes().put(ViewPoolProcessor.ENABLE_VIEW_POOL, !value);
+    }
+    
+    /**
+     * Takes the newView and restore the state taken as base the provided ViewEntry,
+     * and then move all child components from oldView to newView, to finally obtain
+     * a clean component tree.
+     * 
+     * @param context
+     * @param newView
+     * @param entry 
+     */
+    public void cloneAndRestoreView(FacesContext context, UIViewRoot newView, 
+            ViewEntry entry, ViewStructureMetadata metadata)
+    {
+        UIViewRoot oldView = entry.getViewRoot();
+        // retrieveViewRootInitialState(context, oldView)
+        Object viewState = metadata.getViewRootState();
+        if (viewState == null)
+        {
+            // (Optional, it should be always metadata)
+            oldView.clearInitialState();
+            viewState = oldView.saveState(context);
+        }
+        boolean oldProcessingEvents = context.isProcessingEvents();
+        context.setProcessingEvents(false);
+        try
+        {
+            if (oldView.getFacetCount() > 0)
+            {
+                List<String> facetKeys = new ArrayList<String>();
+                facetKeys.addAll(oldView.getFacets().keySet());
+                for (String facetKey : facetKeys)
+                {
+                    //context.setProcessingEvents(false);
+                    UIComponent facet = oldView.getFacets().remove(facetKey);
+                    //context.setProcessingEvents(true);
+                    newView.getFacets().put(facetKey, facet);
+                }
+            }
+            if (oldView.getChildCount() > 0)
+            {
+                for (Iterator<UIComponent> it = oldView.getChildren().iterator(); it.hasNext();)
+                {
+                    //context.setProcessingEvents(false);
+                    UIComponent c = it.next();
+                    it.remove();
+                    //context.setProcessingEvents(true);
+                    newView.getChildren().add(c);
+                }
+            }
+            
+            // Restore the newView as saved just before markInitialState() call
+            newView.restoreState(context, viewState);
+            newView.markInitialState();
+            
+            if (!PhaseId.RESTORE_VIEW.equals(context.getCurrentPhaseId()))
+            {
+                // Restore bindings like in restore view phase, because in this case,
+                // bindings needs to be set (Application.createComponent is not called!).
+                restoreViewSupport.processComponentBinding(context, newView);
+            }
+            
+            // Update request view metadata to ensure resource list is restored as when the
+            // view was built on the first time. This ensures correct calculation of added 
+            // resources by dynamic behavior. 
+            RequestViewContext rcv = RequestViewContext.getCurrentInstance(context, newView, false);
+            if (rcv != null)
+            {
+                rcv.setRequestViewMetadata(metadata.getRequestViewMetadata().cloneInstance());
+            }
+            else
+            {
+                RequestViewContext.setCurrentInstance(context, newView,
+                        RequestViewContext.newInstance(metadata.getRequestViewMetadata().cloneInstance()));
+            }
+        }
+        finally
+        {
+            context.setProcessingEvents(oldProcessingEvents);
+        }
+    }
+    
+    public void storeViewStructureMetadata(FacesContext context, UIViewRoot root)
+    {
+        ViewPool viewPool = getViewPool(context, root);
+        if (viewPool != null)
+        {
+            FaceletState faceletState = (FaceletState) root.getAttributes().get(
+                    ComponentSupport.FACELET_STATE_INSTANCE);
+            boolean isDynamic = faceletState != null ? faceletState.isDynamic() : false;
+            if (!isDynamic)
+            {
+                viewPool.storeStaticViewStructureMetadata(context, root, faceletState);            
+            }
+            else
+            {
+                viewPool.storeDynamicViewStructureMetadata(context, root, faceletState);
+            }
+        }
+    }
+    
+    public ViewStructureMetadata retrieveViewStructureMetadata(FacesContext context,
+            UIViewRoot root)
+    {
+        ViewPool viewPool = getViewPool(context, root);
+        FaceletState faceletState = (FaceletState) root.getAttributes().get(
+                ComponentSupport.FACELET_STATE_INSTANCE);
+        boolean isDynamic = faceletState != null ? faceletState.isDynamic() : false;
+        if (!isDynamic)
+        {
+            return viewPool.retrieveStaticViewStructureMetadata(context, root);
+        }
+        else
+        {
+            return viewPool.retrieveDynamicViewStructureMetadata(context, root, faceletState);
+        }
+    }
+    
+    public void pushResetableView(FacesContext context, UIViewRoot view, FaceletState faceletViewState)
+    {
+        ViewPool viewPool = getViewPool(context, view);
+        boolean isDynamic = faceletViewState != null ? faceletViewState.isDynamic() : false;
+        if (!isDynamic)
+        {
+            clearTransientAndNonFaceletComponentsForStaticView(context, view);
+            viewPool.pushStaticStructureView(context, view);
+        }
+        else
+        {
+            ViewStructureMetadata viewStructureMetadata = viewPool.retrieveDynamicViewStructureMetadata(
+                context, view, faceletViewState);
+            if (viewStructureMetadata != null)
+            {
+                clearTransientAndNonFaceletComponentsForDynamicView(context, view, viewStructureMetadata);
+                viewPool.pushDynamicStructureView(context, view, faceletViewState);
+            }
+        }
+    }
+    
+    public void pushPartialView(FacesContext context, UIViewRoot view, FaceletState faceletViewState, int count)
+    {
+        ViewPool viewPool = getViewPool(context, view);
+        
+        if (viewPool.isWorthToRecycleThisView(context, view))
+        {
+            ViewStructureMetadata viewStructureMetadata = null;
+            if (faceletViewState == null)
+            {
+                viewStructureMetadata = viewPool.retrieveStaticViewStructureMetadata(context, view);
+            }
+            else
+            {
+                viewStructureMetadata = viewPool.retrieveDynamicViewStructureMetadata(
+                    context, view, faceletViewState);
+            }
+            if (viewStructureMetadata != null)
+            {
+                ClearPartialTreeContext ptc = new ClearPartialTreeContext();
+                // add partial structure view to the map.
+                clearTransientAndRemoveNonResetableComponents(context, ptc, view, viewStructureMetadata);
+                int reusableCount = ptc.getCount();
+                float factor = ((float)reusableCount) / ((float)count);
+                if (factor > 0.3f)
+                {
+                    viewPool.pushPartialStructureView(context, view);
+                }
+            }
+        }        
+    }
+    
+    protected void clearTransientAndNonFaceletComponentsForStaticView(final FacesContext context, 
+            final UIViewRoot root)
+    {
+        // In a static view, clear components that are both transient and non bound to any facelet tag handler
+        // is quite simple. Since the structure of the view is static, there is no need to check component resources.
+        clearTransientAndNonFaceletComponents(context, root);
+    }
+    
+    public void clearTransientAndNonFaceletComponentsForDynamicView(final FacesContext context, 
+            final UIViewRoot root, final ViewStructureMetadata viewStructureMetadata)
+    {
+        //Scan children
+        int childCount = root.getChildCount();
+        if (childCount > 0)
+        {
+            for (int i = 0; i < childCount; i++)
+            {
+                UIComponent child = root.getChildren().get(i);
+                if (child != null && child.isTransient() &&
+                    child.getAttributes().get(ComponentSupport.MARK_CREATED) == null)
+                {
+                    root.getChildren().remove(i);
+                    i--;
+                    childCount--;
+                }
+                else
+                {
+                    if (child.getChildCount() > 0 || !child.getFacets().isEmpty())
+                    {
+                        clearTransientAndNonFaceletComponents(context, child);
+                    }
+                }
+            }
+        }
+
+        clearTransientAndNonFaceletComponentsForDynamicViewUIViewRootFacets(
+            context, root, viewStructureMetadata);
+    }
+    
+    private void clearTransientAndNonFaceletComponentsForDynamicViewUIViewRootFacets(final FacesContext context, 
+            final UIViewRoot root, ViewStructureMetadata viewStructureMetadata)
+    {
+        
+        //Scan facets
+        if (root.getFacetCount() > 0)
+        {
+            Map<String, UIComponent> facets = root.getFacets();
+            for (Iterator<UIComponent> itr = facets.values().iterator(); itr.hasNext();)
+            {
+                UIComponent fc = itr.next();
+                if (fc != null && !(fc instanceof ComponentResourceContainer))
+                {
+                    if ( fc.isTransient() &&
+                        fc.getAttributes().get(ComponentSupport.MARK_CREATED) == null)
+                    {
+                        itr.remove();
+                    }
+                    else
+                    {
+                        if (fc.getChildCount() > 0 || !fc.getFacets().isEmpty())
+                        {
+                            clearTransientAndNonFaceletComponents(context, fc);
+                        }
+                    }
+                }
+                else if (fc != null)
+                {
+                    // In a facet which is a ComponentResourceContainer instance,
+                    // we need to check these two cases:
+                    // 1. Resources relocated by facelets
+                    // 2. Resources created by effect of a @ResourceDependency annotation
+                    if (fc.getId() != null && fc.getId().startsWith("javax_faces_location_"))
+                    {
+                        String target = fc.getId().substring("javax_faces_location_".length());
+                        Map<String, List<ResourceDependency>> addedResources = 
+                            viewStructureMetadata.getRequestViewMetadata().
+                                getResourceDependencyAnnotations(context);
+                        List<ResourceDependency> resourceDependencyList = (addedResources != null) ?
+                            addedResources.get(target) : null;
+
+                        clearComponentResourceContainer(context, fc, resourceDependencyList);
+                    }
+                }
+            }
+        }
+    }
+    
+    private void clearComponentResourceContainer(final FacesContext context, UIComponent component,
+        List<ResourceDependency> resourceDependencyList)
+    {
+        //Scan children
+        int childCount = component.getChildCount();
+        if (childCount > 0)
+        {
+            for (int i = 0; i < childCount; i++)
+            {
+                UIComponent child = component.getChildren().get(i);
+                String id = (String) child.getAttributes().get(ComponentSupport.MARK_CREATED);
+                if (child != null && child.isTransient() &&
+                    id == null)
+                {
+                    //Remove both transient not facelets bound components
+                    component.getChildren().remove(i);
+                    i--;
+                    childCount--;
+                }
+                else if (id != null)
+                {
+                    // If it has an id set, it is a facelet component resource.
+                    // The refresh algorithm take care of the cleanup.
+                }
+                /*
+                else if (!child.isTransient() && id != null && !faceletResources.contains(id))
+                {
+                    // check if the resource has a facelet tag in this "dynamic state", if not
+                    // remove it. Really leave a component resource does not harm, but 
+                    // the objective is make this view as close as when if it is built as new.
+                    component.getChildren().remove(i);
+                    i--;
+                    childCount--;
+                }*/
+                else
+                {
+                    // Check if the component instance was created using a @ResourceDependency annotation
+                    Object[] rdk = (Object[]) child.getAttributes().get(
+                                RequestViewMetadata.RESOURCE_DEPENDENCY_KEY);
+                    if (rdk != null)
+                    {
+                        boolean found = false;
+                        String library = (String) rdk[0];
+                        String name = (String) rdk[1];
+                        if (resourceDependencyList != null)
+                        {
+                            for (ResourceDependency resource : resourceDependencyList)
+                            {
+                                if (library == null && resource.library() == null)
+                                {
+                                    if (name != null && name.equals(resource.name()))
+                                    {
+                                        found = true;
+                                        break;
+                                    }
+                                }
+                                else
+                                {
+                                    if (library != null && library.equals(resource.library()) &&
+                                        name != null && name.equals(resource.name()) )
+                                    {
+                                        found = true;
+                                        break;
+                                    }
+                                }
+                            }
+                        }
+                        if (!found)
+                        {
+                            //Remove it, because for this dynamic state it it does not exists.
+                            component.getChildren().remove(i);
+                            i--;
+                            childCount--;
+                        }
+                        // If found just leave it.
+                    }
+                    else
+                    {
+                        if (child.getChildCount() > 0 || !child.getFacets().isEmpty())
+                        {
+                            clearTransientAndNonFaceletComponents(context, child);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Clear all transient components not created by facelets algorithm. In this way,
+     * we ensure the component tree does not have any changes done after markInitialState.
+     * 
+     * @param context
+     * @param component 
+     */
+    private void clearTransientAndNonFaceletComponents(final FacesContext context, final UIComponent component)
+    {
+        //Scan children
+        int childCount = component.getChildCount();
+        if (childCount > 0)
+        {
+            for (int i = 0; i < childCount; i++)
+            {
+                UIComponent child = component.getChildren().get(i);
+                if (child != null && child.isTransient() &&
+                    child.getAttributes().get(ComponentSupport.MARK_CREATED) == null)
+                {
+                    component.getChildren().remove(i);
+                    i--;
+                    childCount--;
+                }
+                else
+                {
+                    if (child.getChildCount() > 0 || !child.getFacets().isEmpty())
+                    {
+                        clearTransientAndNonFaceletComponents(context, child);
+                    }
+                }
+            }
+        }
+
+        //Scan facets
+        if (component.getFacetCount() > 0)
+        {
+            Map<String, UIComponent> facets = component.getFacets();
+            for (Iterator<UIComponent> itr = facets.values().iterator(); itr.hasNext();)
+            {
+                UIComponent fc = itr.next();
+                if (fc != null && fc.isTransient() &&
+                    fc.getAttributes().get(ComponentSupport.MARK_CREATED) == null)
+                {
+                    itr.remove();
+                }
+                else
+                {
+                    if (fc.getChildCount() > 0 || !fc.getFacets().isEmpty())
+                    {
+                        clearTransientAndNonFaceletComponents(context, fc);
+                    }
+                }
+            }
+        }
+    }
+
+    private void clearTransientAndRemoveNonResetableComponents(final FacesContext context, 
+        final ClearPartialTreeContext ptc, final UIViewRoot root, 
+        ViewStructureMetadata viewStructureMetadata)
+    {
+        //Scan children
+        int childCount = root.getChildCount();
+
+        try
+        {
+            root.getAttributes().put(ViewPoolProcessor.RESET_SAVE_STATE_MODE_KEY, 
+                        ViewPoolProcessor.RESET_MODE_HARD);
+            if (childCount > 0)
+            {
+                for (int i = 0; i < childCount; i++)
+                {
+                    UIComponent child = root.getChildren().get(i);
+                    boolean containsFaceletId = child.getAttributes().containsKey(ComponentSupport.MARK_CREATED);
+                    if (child != null && child.isTransient() && !containsFaceletId)
+                    {
+                        //Transient and not bound to facelets tag, remove it!.
+                        root.getChildren().remove(i);
+                        i--;
+                        childCount--;
+                    }
+                    else
+                    {
+                        if (child.getAttributes().containsKey(ComponentSupport.COMPONENT_ADDED_BY_HANDLER_MARKER))
+                        {
+                            //Dynamically added or moved, remove it!
+                            root.getChildren().remove(i);
+                            i--;
+                            childCount--;
+
+                        }
+                        else if (containsFaceletId ||
+                            child.getAttributes().containsKey(ComponentSupport.COMPONENT_ADDED_BY_HANDLER_MARKER))
+                        {
+                            // Bound to a facelet tag or created by facelets, we have two options:
+                            // 1. If is not transient, check its state and try to clear it, if fails remove it
+                            // 2. If is transient, assume stateless, continue.
+                            if (!child.isTransient())
+                            {
+                                // Remember that hard reset is already enabled.
+                                Object state = child.saveState(context);
+                                if (state == null)
+                                {
+                                    if (child.getChildCount() > 0 || !child.getFacets().isEmpty())
+                                    {
+                                        clearTransientAndRemoveNonResetableComponents(context, ptc, child);
+                                    }
+                                    ptc.incrementCount();
+                                }
+                                else
+                                {
+                                    root.getChildren().remove(i);
+                                    i--;
+                                    childCount--;
+                                }
+                            }
+                            else
+                            {
+                                ptc.incrementCount();
+                            }
+                        }
+                        else
+                        {
+                            // Non facelets component, remove it!.
+                            root.getChildren().remove(i);
+                            i--;
+                            childCount--;
+                        }
+                    }
+                }
+            }
+
+            clearTransientAndNonFaceletComponentsForDynamicViewUIViewRootFacets(
+                context, root, viewStructureMetadata);
+        }
+        finally
+        {
+            root.getAttributes().put(ViewPoolProcessor.RESET_SAVE_STATE_MODE_KEY, 
+                        ViewPoolProcessor.RESET_MODE_OFF);
+        }
+    }
+    
+    private void clearTransientAndRemoveNonResetableComponents(final FacesContext context,
+        final ClearPartialTreeContext ptc, final UIComponent component)
+    {
+        //Scan children
+        int childCount = component.getChildCount();
+        if (childCount > 0)
+        {
+            for (int i = 0; i < childCount; i++)
+            {
+                UIComponent child = component.getChildren().get(i);
+                boolean containsFaceletId = child.getAttributes().containsKey(ComponentSupport.MARK_CREATED);
+                if (child != null && child.isTransient() && !containsFaceletId)
+                {
+                    //Transient and not bound to facelets tag, remove it!.
+                    component.getChildren().remove(i);
+                    i--;
+                    childCount--;
+                }
+                else
+                {
+                    if (child.getAttributes().containsKey(ComponentSupport.COMPONENT_ADDED_BY_HANDLER_MARKER))
+                    {
+                        //Dynamically added or moved, remove it!
+                        component.getChildren().remove(i);
+                        i--;
+                        childCount--;
+
+                    }
+                    else if (containsFaceletId ||
+                        child.getAttributes().containsKey(ComponentSupport.COMPONENT_ADDED_BY_HANDLER_MARKER))
+                    {
+                        // Bound to a facelet tag or created by facelets, we have two options:
+                        // 1. If is not transient, check its state and try to clear it, if fails remove it
+                        // 2. If is transient, assume stateless, continue.
+                        if (!child.isTransient())
+                        {
+                            // Remember that hard reset is already enabled.
+                            Object state = child.saveState(context);
+                            if (state == null)
+                            {
+                                if (child.getChildCount() > 0 || !child.getFacets().isEmpty())
+                                {
+                                    clearTransientAndRemoveNonResetableComponents(context, ptc, child);
+                                }
+                                ptc.incrementCount();
+                            }
+                            else
+                            {
+                                component.getChildren().remove(i);
+                                i--;
+                                childCount--;
+                            }
+                        }
+                        else
+                        {
+                            ptc.incrementCount();
+                        }
+                    }
+                    else
+                    {
+                        // Non facelets component, remove it!.
+                        component.getChildren().remove(i);
+                        i--;
+                        childCount--;
+                    }
+                }
+            }
+        }
+
+        //Scan facets
+        if (component.getFacetCount() > 0)
+        {
+            Map<String, UIComponent> facets = component.getFacets();
+            for (Iterator<UIComponent> itr = facets.values().iterator(); itr.hasNext();)
+            {
+                UIComponent fc = itr.next();
+                boolean containsFaceletId = fc.getAttributes().containsKey(ComponentSupport.MARK_CREATED);
+                if (fc != null && fc.isTransient() && !containsFaceletId)
+                {
+                    //Transient and not bound to facelets tag, remove it!.
+                    itr.remove();
+                }
+                else
+                {
+                    if (fc.getAttributes().containsKey(ComponentSupport.COMPONENT_ADDED_BY_HANDLER_MARKER))
+                    {
+                        //Dynamically added or moved, remove it!
+                        itr.remove();
+
+                    }
+                    else if (containsFaceletId ||
+                        fc.getAttributes().containsKey(ComponentSupport.COMPONENT_ADDED_BY_HANDLER_MARKER))
+                    {
+                        // Bound to a facelet tag or created by facelets, we have two options:
+                        // 1. If is not transient, check its state and try to clear it, if fails remove it
+                        // 2. If is transient, assume stateless, continue.
+                        if (!fc.isTransient())
+                        {
+                            // Remember that hard reset is already enabled.
+                            Object state = fc.saveState(context);
+                            if (state == null)
+                            {
+                                if (fc.getChildCount() > 0 || !fc.getFacets().isEmpty())
+                                {
+                                    clearTransientAndRemoveNonResetableComponents(context, ptc, fc);
+                                }
+                                ptc.incrementCount();
+                            }
+                            else
+                            {
+                                itr.remove();
+                            }
+                        }
+                        else
+                        {
+                            ptc.incrementCount();
+                        }
+                    }
+                    else
+                    {
+                        // Non facelets component, remove it!.
+                        itr.remove();
+                    }
+                }
+            }
+        }
+    }
+    
+    public void processDeferredNavigation(FacesContext facesContext)
+    {
+            Object[] command = (Object[]) facesContext.getAttributes().get(
+                ViewPoolProcessor.INVOKE_DEFERRED_NAVIGATION);
+        if (command != null)
+        {
+            try
+            {
+                facesContext.getAttributes().put(ViewPoolProcessor.DISPOSE_VIEW_NAVIGATION, Boolean.TRUE);
+                NavigationHandler navigationHandler = facesContext.getApplication().getNavigationHandler();
+                if (command.length == 3)
+                {
+                    navigationHandler.handleNavigation(facesContext, (String) command[0], (String) command[1], 
+                        (String) command[2]);
+                }
+                else
+                {
+                    navigationHandler.handleNavigation(facesContext, (String) command[0], (String) command[1]);
+                }
+                //Render Response if needed
+                facesContext.renderResponse();
+                facesContext.getAttributes().remove(ViewPoolProcessor.INVOKE_DEFERRED_NAVIGATION);
+            }
+            finally
+            {
+                facesContext.getAttributes().remove(ViewPoolProcessor.DISPOSE_VIEW_NAVIGATION);
+            }
+        }
+    }
+    
+    private static final String SERIALIZED_VIEW_REQUEST_ATTR = 
+        StateManagerImpl.class.getName() + ".SERIALIZED_VIEW";
+
+    public void disposeView(FacesContext facesContext, UIViewRoot root)
+    {
+        if (root == null)
+        {
+            return;
+        }
+
+        String viewId = root.getViewId();
+        if (viewId == null)
+        {
+            return;
+        }
+        Application app = facesContext.getApplication();
+        if (app == null)
+        {
+            return;
+        }
+        ViewHandler viewHandler = app.getViewHandler();
+        if (viewHandler == null)
+        {
+            return;
+        }
+
+        if (Boolean.TRUE.equals(facesContext.getAttributes().get(ViewPoolProcessor.DISPOSE_VIEW_NAVIGATION)))
+        {
+            ViewDeclarationLanguage vdl = facesContext.getApplication().
+                    getViewHandler().getViewDeclarationLanguage(
+                        facesContext, root.getViewId());
+
+            if (vdl != null && ViewDeclarationLanguage.FACELETS_VIEW_DECLARATION_LANGUAGE_ID.equals(vdl.getId()))
+            {
+                StateManagementStrategy sms = vdl.getStateManagementStrategy(facesContext, root.getId());
+                if (sms != null)
+                {
+                    // Force indirectly to store the map in the pool
+                    facesContext.getAttributes().put(ViewPoolProcessor.FORCE_HARD_RESET, Boolean.TRUE);
+
+                    try
+                    {
+                        Object state = sms.saveView(facesContext);
+                    }
+                    finally
+                    {
+                        facesContext.getAttributes().remove(ViewPoolProcessor.FORCE_HARD_RESET);
+                    }
+
+                    // Clear the calculated value from the application map
+                    facesContext.getAttributes().remove(SERIALIZED_VIEW_REQUEST_ATTR);
+                }
+            }
+        }
+    }
+    
+    private static class ClearPartialTreeContext 
+    {
+        private int count;
+        
+        public ClearPartialTreeContext()
+        {
+            count = 0;
+        }
+
+        /**
+         * @return the count
+         */
+        public int getCount()
+        {
+            return count;
+        }
+
+        public int incrementCount()
+        {
+            return count++;
+        }
+        /**
+         * @param count the count to set
+         */
+        public void setCount(int count)
+        {
+            this.count = count;
+        }
+    }
+}

Propchange: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/ViewPoolProcessor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/pool/RestoreViewFromPoolResult.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/pool/RestoreViewFromPoolResult.java?rev=1550609&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/pool/RestoreViewFromPoolResult.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/pool/RestoreViewFromPoolResult.java Fri Dec 13 01:18:08 2013
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.view.facelets.pool;
+
+/**
+ * 
+ */
+public enum RestoreViewFromPoolResult
+{
+    /**
+     * Indicate the view is ready to use.
+     */
+    COMPLETE,
+    
+    /**
+     * Indicate the view requires to be refreshed by facelets algorithm.
+     */
+    REFRESH_REQUIRED
+}

Propchange: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/pool/RestoreViewFromPoolResult.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/pool/ViewEntry.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/pool/ViewEntry.java?rev=1550609&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/pool/ViewEntry.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/pool/ViewEntry.java Fri Dec 13 01:18:08 2013
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.view.facelets.pool;
+
+import javax.faces.component.UIViewRoot;
+
+/**
+ *
+ * @author Leonardo Uribe
+ */
+public abstract class ViewEntry
+{
+    /**
+     * @return the viewRoot
+     */
+    public abstract UIViewRoot getViewRoot();
+
+    /**
+     * Execute all necessary steps to ensure further calls to 
+     * getViewRoot() and getViewState() will return valid values.
+     * It returns true or false if the Entry is still active or not
+     * 
+     */
+    public abstract boolean activate();
+    
+    /**
+     * @return the result
+     */
+    public abstract RestoreViewFromPoolResult getResult();
+
+    /**
+     * @param result the result to set
+     */
+    public abstract void setResult(RestoreViewFromPoolResult result);
+
+}

Propchange: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/pool/ViewEntry.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/pool/ViewPool.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/pool/ViewPool.java?rev=1550609&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/pool/ViewPool.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/pool/ViewPool.java Fri Dec 13 01:18:08 2013
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.view.facelets.pool;
+
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.FacesContext;
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
+import org.apache.myfaces.view.facelets.tag.jsf.FaceletState;
+
+/**
+ * This class defines the necessary operations that a view pool should comply in
+ * order to be used by MyFaces.
+ * 
+ * <p>A View Pool is a set of initialized views that are kept ready to use. The idea 
+ * is reset and reuse views taking advantage of existing JSF 2.0 Partial State 
+ * Saving algorithm with some small additions to component's saveState() method.
+ * </p>
+ * <p>This technique works by these reasons:
+ * </p>
+ * <ul>
+ * <li>A view is composed by many small objects that are created multiple times per
+ * each request, and the time spent creating these objects is usually larger than 
+ * the time used to traverse the component tree.</li>
+ * <li>The structure of a view usually does not change over application lifetime.</li>
+ * <li>The "delta state" or in other words the elements that change in view are
+ * small compared with the elements that does not change.</li>
+ * <ul>
+ * <p>
+ * The implementation proposed uses a lock free view pool structure with soft or
+ * weak references. The lock free view pool ensures fast access and the soft or weak
+ * references ensured the garbage collection algorithm is not affected by the view
+ * pool.
+ * </p>
+ *
+ * @author Leonardo Uribe
+ */
+public abstract class ViewPool
+{
+    /**
+     * Defines the number of views to be hold per each view metadata definition.
+     * By default is 5. 
+     * 
+     * Usually a view is defined by its viewId, locale, renderKitId
+     * and active contracts. If a view shares the same values for these parameters
+     * belongs to the same group that can be pooled.
+     */
+    @JSFWebConfigParam(defaultValue="5", tags="performance")
+    public static final String INIT_PARAM_VIEW_POOL_MAX_POOL_SIZE =
+            "org.apache.myfaces.VIEW_POOL_MAX_POOL_SIZE";
+    public static final int INIT_PARAM_VIEW_POOL_MAX_POOL_SIZE_DEFAULT = 5;
+    
+    /**
+     * Defines the limit of the views that cannot be reused partially.
+     */
+    @JSFWebConfigParam(defaultValue="2", tags="performance")
+    public static final String INIT_PARAM_VIEW_POOL_MAX_DYNAMIC_PARTIAL_LIMIT =
+            "org.apache.myfaces.VIEW_POOL_MAX_DYNAMIC_PARTIAL_LIMIT";
+    public static final int INIT_PARAM_VIEW_POOL_MAX_DYNAMIC_PARTIAL_LIMIT_DEFAULT = 2;
+    
+    /**
+     * Defines the type of memory reference that is used to hold the view into memory. By
+     * default a "soft" reference is used. 
+     */
+    @JSFWebConfigParam(defaultValue="soft", expectedValues="weak,soft", tags="performance")
+    public static final String INIT_PARAM_VIEW_POOL_ENTRY_MODE =
+            "org.apache.myfaces.VIEW_POOL_ENTRY_MODE";
+    public static final String ENTRY_MODE_SOFT = "soft";
+    public static final String ENTRY_MODE_WEAK = "weak";
+    public static final String INIT_PARAM_VIEW_POOL_ENTRY_MODE_DEFAULT = ENTRY_MODE_SOFT;
+    
+    /**
+     * Defines if the view pool uses deferred navigation to recycle views when navigation
+     * is performed. The difference is a normal navigation is not done when the broadcast is
+     * done but at the end of invoke application phase.
+     */
+    @JSFWebConfigParam(defaultValue="false", expectedValues="true, false", tags="performance")
+    public static final String INIT_PARAM_VIEW_POOL_DEFERRED_NAVIGATION =
+            "org.apache.myfaces.VIEW_POOL_DEFERRED_NAVIGATION";    
+    
+    /**
+     * Indicate if the view pool uses deferred navigation.
+     * 
+     * @return 
+     */
+    public abstract boolean isDeferredNavigationEnabled();
+    
+    public abstract void storeStaticViewStructureMetadata(FacesContext context, 
+        UIViewRoot root, FaceletState faceletState);
+    
+    public abstract ViewStructureMetadata retrieveStaticViewStructureMetadata(FacesContext context,
+            UIViewRoot root);
+    
+    public abstract void pushStaticStructureView(FacesContext context, UIViewRoot root);
+
+    public abstract void pushPartialStructureView(FacesContext context, UIViewRoot root);
+    
+    public abstract ViewEntry popStaticOrPartialStructureView(FacesContext context, UIViewRoot root);
+
+    public abstract boolean isWorthToRecycleThisView(FacesContext context, UIViewRoot root);
+    
+    public abstract void storeDynamicViewStructureMetadata(FacesContext context, 
+            UIViewRoot root, FaceletState faceletState);
+    
+    public abstract ViewStructureMetadata retrieveDynamicViewStructureMetadata(FacesContext context,
+            UIViewRoot root, FaceletState faceletState);
+
+    public abstract void pushDynamicStructureView(FacesContext context, UIViewRoot root, 
+            FaceletState faceletDynamicState);
+    
+    public abstract ViewEntry popDynamicStructureView(FacesContext context, UIViewRoot root,
+            FaceletState faceletDynamicState);
+
+}

Propchange: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/pool/ViewPool.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/pool/ViewPoolFactory.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/pool/ViewPoolFactory.java?rev=1550609&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/pool/ViewPoolFactory.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/pool/ViewPoolFactory.java Fri Dec 13 01:18:08 2013
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.view.facelets.pool;
+
+import javax.faces.FacesWrapper;
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.FacesContext;
+
+/**
+ *
+ * @author Leonardo Uribe
+ */
+public abstract class ViewPoolFactory implements FacesWrapper<ViewPoolFactory>
+{
+    
+    public abstract ViewPool getViewPool(FacesContext context, 
+            UIViewRoot recyclableRoot);
+
+    public ViewPoolFactory getWrapped()
+    {
+        return null;
+    }
+
+}

Propchange: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/pool/ViewPoolFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native