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 2011/08/21 03:25:11 UTC

svn commit: r1159933 - in /myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces: application/StateManagerImpl.java view/facelets/DefaultFaceletsStateManagementStrategy.java view/facelets/FaceletViewDeclarationLanguage.java

Author: lu4242
Date: Sun Aug 21 01:25:10 2011
New Revision: 1159933

URL: http://svn.apache.org/viewvc?rev=1159933&view=rev
Log:
MYFACES-3257 Clarify partial state save/restore traversal requirements

Modified:
    myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/application/StateManagerImpl.java
    myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementStrategy.java
    myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java

Modified: myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/application/StateManagerImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/application/StateManagerImpl.java?rev=1159933&r1=1159932&r2=1159933&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/application/StateManagerImpl.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/application/StateManagerImpl.java Sun Aug 21 01:25:10 2011
@@ -47,6 +47,8 @@ public class StateManagerImpl extends St
     private static final String SERIALIZED_VIEW_REQUEST_ATTR = 
         StateManagerImpl.class.getName() + ".SERIALIZED_VIEW";
     
+    private static final String IS_SAVING_STATE = "javax.faces.IS_SAVING_STATE";
+    
     private RenderKitFactory _renderKitFactory = null;
     
     public StateManagerImpl()
@@ -149,70 +151,79 @@ public class StateManagerImpl extends St
         String viewId = uiViewRoot.getViewId();
         ViewDeclarationLanguage vdl = facesContext.getApplication().
             getViewHandler().getViewDeclarationLanguage(facesContext,viewId);
-        if (vdl != null)
+        
+        try
         {
-            StateManagementStrategy sms = vdl.getStateManagementStrategy(facesContext, viewId);
-            
-            if (sms != null)
+            facesContext.getAttributes().put(IS_SAVING_STATE, Boolean.TRUE);
+            if (vdl != null)
             {
-                if (log.isLoggable(Level.FINEST)) log.finest("Calling saveView of StateManagementStrategy: "+sms.getClass().getName());
-                
-                serializedView = sms.saveView(facesContext);
+                StateManagementStrategy sms = vdl.getStateManagementStrategy(facesContext, viewId);
                 
-                // If MyfacesResponseStateManager is used, give the option to do
-                // additional operations for save the state if is necessary.
-                if (StateCacheUtils.isMyFacesResponseStateManager(responseStateManager))
+                if (sms != null)
                 {
-                    StateCacheUtils.getMyFacesResponseStateManager(responseStateManager).saveState(facesContext, serializedView);
+                    if (log.isLoggable(Level.FINEST)) log.finest("Calling saveView of StateManagementStrategy: "+sms.getClass().getName());
+                    
+                    serializedView = sms.saveView(facesContext);
+                    
+                    // If MyfacesResponseStateManager is used, give the option to do
+                    // additional operations for save the state if is necessary.
+                    if (StateCacheUtils.isMyFacesResponseStateManager(responseStateManager))
+                    {
+                        StateCacheUtils.getMyFacesResponseStateManager(responseStateManager).saveState(facesContext, serializedView);
+                    }
+                    
+                    return serializedView; 
                 }
-                
-                return serializedView; 
             }
+    
+            // In StateManagementStrategy.saveView there is a check for transient at
+            // start, but the same applies for VDL without StateManagementStrategy,
+            // so this should be checked before call parent (note that parent method
+            // does not do this check).
+            if (uiViewRoot.isTransient())
+            {
+                return null;
+            }
+    
+            if (log.isLoggable(Level.FINEST)) log.finest("Entering saveSerializedView");
+    
+            checkForDuplicateIds(facesContext, facesContext.getViewRoot(), new HashSet<String>());
+    
+            if (log.isLoggable(Level.FINEST)) log.finest("Processing saveSerializedView - Checked for duplicate Ids");
+    
+            ExternalContext externalContext = facesContext.getExternalContext();
+    
+            // SerializedView already created before within this request?
+            serializedView = externalContext.getRequestMap()
+                                                                .get(SERIALIZED_VIEW_REQUEST_ATTR);
+            if (serializedView == null)
+            {
+                if (log.isLoggable(Level.FINEST)) log.finest("Processing saveSerializedView - create new serialized view");
+    
+                // first call to saveSerializedView --> create SerializedView
+                Object treeStruct = getTreeStructureToSave(facesContext);
+                Object compStates = getComponentStateToSave(facesContext);
+                serializedView = new Object[] {treeStruct, compStates};
+                externalContext.getRequestMap().put(SERIALIZED_VIEW_REQUEST_ATTR,
+                                                    serializedView);
+    
+                if (log.isLoggable(Level.FINEST)) log.finest("Processing saveSerializedView - new serialized view created");
+            }
+            
+            // If MyfacesResponseStateManager is used, give the option to do
+            // additional operations for save the state if is necessary.
+            if (StateCacheUtils.isMyFacesResponseStateManager(responseStateManager))
+            {
+                StateCacheUtils.getMyFacesResponseStateManager(responseStateManager).saveState(facesContext, serializedView);
+            }
+    
+            if (log.isLoggable(Level.FINEST)) log.finest("Exiting saveView");
         }
-
-        // In StateManagementStrategy.saveView there is a check for transient at
-        // start, but the same applies for VDL without StateManagementStrategy,
-        // so this should be checked before call parent (note that parent method
-        // does not do this check).
-        if (uiViewRoot.isTransient())
-        {
-            return null;
-        }
-
-        if (log.isLoggable(Level.FINEST)) log.finest("Entering saveSerializedView");
-
-        checkForDuplicateIds(facesContext, facesContext.getViewRoot(), new HashSet<String>());
-
-        if (log.isLoggable(Level.FINEST)) log.finest("Processing saveSerializedView - Checked for duplicate Ids");
-
-        ExternalContext externalContext = facesContext.getExternalContext();
-
-        // SerializedView already created before within this request?
-        serializedView = externalContext.getRequestMap()
-                                                            .get(SERIALIZED_VIEW_REQUEST_ATTR);
-        if (serializedView == null)
-        {
-            if (log.isLoggable(Level.FINEST)) log.finest("Processing saveSerializedView - create new serialized view");
-
-            // first call to saveSerializedView --> create SerializedView
-            Object treeStruct = getTreeStructureToSave(facesContext);
-            Object compStates = getComponentStateToSave(facesContext);
-            serializedView = new Object[] {treeStruct, compStates};
-            externalContext.getRequestMap().put(SERIALIZED_VIEW_REQUEST_ATTR,
-                                                serializedView);
-
-            if (log.isLoggable(Level.FINEST)) log.finest("Processing saveSerializedView - new serialized view created");
-        }
-        
-        // If MyfacesResponseStateManager is used, give the option to do
-        // additional operations for save the state if is necessary.
-        if (StateCacheUtils.isMyFacesResponseStateManager(responseStateManager))
+        finally
         {
-            StateCacheUtils.getMyFacesResponseStateManager(responseStateManager).saveState(facesContext, serializedView);
+            facesContext.getAttributes().remove(IS_SAVING_STATE);
         }
 
-        if (log.isLoggable(Level.FINEST)) log.finest("Exiting saveView");
-
         return serializedView;
     }
 
@@ -234,11 +245,18 @@ public class StateManagerImpl extends St
             ids = new HashSet<String>();
         }
         
-        Iterator<UIComponent> it = component.getFacetsAndChildren();
-        while (it.hasNext())
+        int facetCount = component.getFacetCount();
+        if (facetCount > 0)
+        {
+            for (UIComponent facet : component.getFacets().values())
+            {
+                checkForDuplicateIds (context, facet, ids);
+            }
+        }
+        for (int i = 0, childCount = component.getChildCount(); i < childCount; i++)
         {
-            UIComponent kid = it.next();
-            checkForDuplicateIds(context, kid, ids);
+            UIComponent child = component.getChildren().get(i);
+            checkForDuplicateIds (context, child, ids);
         }
     }
 

Modified: myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementStrategy.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementStrategy.java?rev=1159933&r1=1159932&r2=1159933&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementStrategy.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/DefaultFaceletsStateManagementStrategy.java Sun Aug 21 01:25:10 2011
@@ -34,13 +34,15 @@ import javax.faces.component.ContextCall
 import javax.faces.component.UIComponent;
 import javax.faces.component.UIViewParameter;
 import javax.faces.component.UIViewRoot;
+import javax.faces.component.visit.VisitCallback;
+import javax.faces.component.visit.VisitContext;
+import javax.faces.component.visit.VisitResult;
 import javax.faces.context.ExternalContext;
 import javax.faces.context.FacesContext;
 import javax.faces.event.PostAddToViewEvent;
 import javax.faces.event.PreRemoveFromViewEvent;
 import javax.faces.event.SystemEvent;
 import javax.faces.event.SystemEventListener;
-import javax.faces.render.RenderKit;
 import javax.faces.render.RenderKitFactory;
 import javax.faces.render.ResponseStateManager;
 import javax.faces.view.StateManagementStrategy;
@@ -49,9 +51,10 @@ import javax.faces.view.ViewDeclarationL
 import javax.faces.view.ViewMetadata;
 
 import org.apache.myfaces.application.StateManagerImpl;
-import org.apache.myfaces.shared.renderkit.RendererUtils;
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
 import org.apache.myfaces.shared.util.ClassUtils;
 import org.apache.myfaces.shared.util.HashMapUtils;
+import org.apache.myfaces.shared.util.WebConfigParamUtils;
 
 /**
  * This class implements partial state saving feature when facelets
@@ -112,6 +115,17 @@ public class DefaultFaceletsStateManagem
      */
     public  static final String COMPONENT_ADDED_AFTER_BUILD_VIEW = "oam.COMPONENT_ADDED_AFTER_BUILD_VIEW"; 
     
+    /**
+     * If this param is set to true (by default), when pss algorithm is executed to save state, a visit tree
+     * traversal is done, instead a plain traversal like previous versions (2.0.7/2.1.1 and earlier) of MyFaces Core.
+     * 
+     * This param is just provided to preserve backwards behavior. 
+     */
+    @JSFWebConfigParam(since="2.0.8, 2.1.2", defaultValue="true", expectedValues="true, false")
+    public static final String SAVE_STATE_WITH_VISIT_TREE_ON_PSS = "org.apache.myfaces.SAVE_STATE_WITH_VISIT_TREE_ON_PSS";
+    
+    private static final String SKIP_ITERATION_HINT = "javax.faces.visit.SKIP_ITERATION";
+    
     private static final String SERIALIZED_VIEW_REQUEST_ATTR = 
         StateManagerImpl.class.getName() + ".SERIALIZED_VIEW";
     
@@ -119,6 +133,8 @@ public class DefaultFaceletsStateManagem
     
     private RenderKitFactory _renderKitFactory = null;
     
+    private Boolean _saveStateWithVisitTreeOnPSS;
+    
     public DefaultFaceletsStateManagementStrategy ()
     {
         _vdlFactory = (ViewDeclarationLanguageFactory)FactoryFinder.getFactory(FactoryFinder.VIEW_DECLARATION_LANGUAGE_FACTORY);
@@ -449,7 +465,14 @@ public class DefaultFaceletsStateManagem
             {
                 states = new HashMap<String, Object>();
 
-                saveStateOnMap(context,(Map<String,Object>) states, view);
+                if (isSaveStateWithVisitTreeOnPSS(context))
+                {
+                    saveStateOnMapVisitTree(context,(Map<String,Object>) states, view);
+                }
+                else
+                {
+                    saveStateOnMap(context,(Map<String,Object>) states, view);
+                }
                 
                 if ( ((Map<String,Object>)states).isEmpty())
                 {
@@ -626,7 +649,123 @@ public class DefaultFaceletsStateManagem
 
         setClientsIdsAdded(uiViewRoot, clientIdsAdded);
     }
+
+    public boolean isSaveStateWithVisitTreeOnPSS(FacesContext facesContext)
+    {
+        if (_saveStateWithVisitTreeOnPSS == null)
+        {
+            _saveStateWithVisitTreeOnPSS = WebConfigParamUtils.getBooleanInitParameter(facesContext.getExternalContext(),
+                    SAVE_STATE_WITH_VISIT_TREE_ON_PSS, Boolean.TRUE);
+        }
+        return Boolean.TRUE.equals(_saveStateWithVisitTreeOnPSS);
+    }
+
+    private void saveStateOnMapVisitTree(final FacesContext facesContext, final Map<String,Object> states,
+            final UIViewRoot uiViewRoot)
+    {
+        facesContext.getAttributes().put(SKIP_ITERATION_HINT, Boolean.TRUE);
+        try
+        {
+            uiViewRoot.visitTree( VisitContext.createVisitContext (facesContext), new VisitCallback()
+            {
+                public VisitResult visit(VisitContext context, UIComponent target)
+                {
+                    FacesContext facesContext = context.getFacesContext();
+                    Object state;
+                    
+                    if ((target == null) || target.isTransient()) {
+                        // No need to bother with these components or their children.
+                        
+                        return VisitResult.REJECT;
+                    }
+                    
+                    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))
+                    {
+                        if (ComponentState.REMOVE_ADD.equals(componentAddedAfterBuildView))
+                        {
+                            registerOnAddRemoveList(target.getClientId());
+                            target.getAttributes().put(COMPONENT_ADDED_AFTER_BUILD_VIEW, ComponentState.ADDED);
+                        }
+                        else if (ComponentState.ADD.equals(componentAddedAfterBuildView))
+                        {
+                            registerOnAddList(target.getClientId());
+                            target.getAttributes().put(COMPONENT_ADDED_AFTER_BUILD_VIEW, ComponentState.ADDED);
+                        }
+                        else if (ComponentState.ADDED.equals(componentAddedAfterBuildView))
+                        {
+                            registerOnAddList(target.getClientId());
+                        }
+                        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;
+                            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 (uiViewRoot.getParent() != null)
+                    {
+                        state = target.saveState (facesContext);
+                        
+                        if (state != null) {
+                            // Save by client ID into our map.
+                            
+                            states.put (target.getClientId (facesContext), state);
+                        }
+                        
+                        return VisitResult.ACCEPT;
+                    }
+                    else
+                    {
+                        //Only UIViewRoot has no parent in a component tree.
+                        return VisitResult.ACCEPT;
+                    }
+                }
+            });
+        }
+        finally
+        {
+            facesContext.getAttributes().remove(SKIP_ITERATION_HINT);
+        }
+        
+        Object state = uiViewRoot.saveState (facesContext);
+        if (state != null) {
+            // Save by client ID into our map.
             
+            states.put (uiViewRoot.getClientId (facesContext), state);
+        }
+    }
+
     private void saveStateOnMap(final FacesContext context, final Map<String,Object> states,
             final UIComponent component)
     {
@@ -749,8 +888,9 @@ public class DefaultFaceletsStateManagem
         c.clearInitialState();
         if (c.getChildCount() > 0)
         {
-            for (UIComponent child : c.getChildren())
+            for (int i = 0, childCount = c.getChildCount(); i < childCount; i++)
             {
+                UIComponent child = c.getChildren().get(i);
                 ensureClearInitialState(child);
             }
         }
@@ -789,10 +929,18 @@ public class DefaultFaceletsStateManagem
         
         existingIds.add (id);
         
-        children = component.getFacetsAndChildren();
-        
-        while (children.hasNext()) {
-            checkIds (context, children.next(), existingIds);
+        int facetCount = component.getFacetCount();
+        if (facetCount > 0)
+        {
+            for (UIComponent facet : component.getFacets().values())
+            {
+                checkIds (context, facet, existingIds);
+            }
+        }
+        for (int i = 0, childCount = component.getChildCount(); i < childCount; i++)
+        {
+            UIComponent child = component.getChildren().get(i);
+            checkIds (context, child, existingIds);
         }
     }
     
@@ -951,8 +1099,9 @@ public class DefaultFaceletsStateManagem
         if (component.getChildCount() > 0)
         {
             List<TreeStructComponent> structChildList = new ArrayList<TreeStructComponent>();
-            for (UIComponent child : component.getChildren())
+            for (int i = 0, childCount = component.getChildCount(); i < childCount; i++)
             {
+                UIComponent child = component.getChildren().get(i);     
                 if (!child.isTransient())
                 {
                     TreeStructComponent structChild = internalBuildTreeStructureToSave(child);

Modified: myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java?rev=1159933&r1=1159932&r2=1159933&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletViewDeclarationLanguage.java Sun Aug 21 01:25:10 2011
@@ -239,6 +239,8 @@ public class FaceletViewDeclarationLangu
     public final static String CLEAN_TRANSIENT_BUILD_ON_RESTORE = "org.apache.myfaces.CLEAN_TRANSIENT_BUILD_ON_RESTORE";
 
     private final static String STATE_KEY = "<!-...@-->";
+    
+    private static final String IS_BUILDING_INITIAL_STATE = "javax.faces.IS_BUILDING_INITIAL_STATE";
 
     private final static int STATE_KEY_LEN = STATE_KEY.length();
 
@@ -311,6 +313,7 @@ public class FaceletViewDeclarationLangu
             if (!refreshTransientBuild)
             {
                 context.getAttributes().put(MARK_INITIAL_STATE_KEY, Boolean.TRUE);
+                context.getAttributes().put(IS_BUILDING_INITIAL_STATE, Boolean.TRUE);
             }
             if (refreshTransientBuildOnPSS)
             {
@@ -397,6 +400,7 @@ public class FaceletViewDeclarationLangu
                 //Remove the key that indicate we need to call UIComponent.markInitialState
                 //on the current tree
                 context.getAttributes().remove(MARK_INITIAL_STATE_KEY);
+                context.getAttributes().remove(IS_BUILDING_INITIAL_STATE);
             }
             
             // We need to suscribe the listeners of changes in the component tree