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