public void saveState(FacesContext facesContext) {
logger.debug("saveState(facesContext)");
// Get the ExternalContext and PortletResponse.
BridgeContext bridgeContext = BridgeContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
PortletResponse portletResponse = (PortletResponse) facesContext.getExternalContext().getResponse();
if ((beganInPhase == Bridge.PortletPhase.ACTION_PHASE) || (beganInPhase == Bridge.PortletPhase.EVENT_PHASE) ||
(beganInPhase == Bridge.PortletPhase.RESOURCE_PHASE)) {
// Save the view root.
setAttribute(BRIDGE_REQ_SCOPE_ATTR_FACES_VIEW_ROOT, facesContext.getViewRoot());
// If the PortletMode hasn't changed, then preserve the "javax.faces.ViewState" request parameter value.
if (!isPortletModeChanged()) {
if (portletResponse instanceof ActionResponse) {
String viewState = facesContext.getExternalContext().getRequestParameterMap().get(
ResponseStateManager.VIEW_STATE_PARAM);
if (viewState != null) {
// NOTE: Although it is possible to save this as a render parameter, can't use that approach
// because portlet containers like Pluto will add the "javax.faces.ViewState" parameter to any
// ResourceURLs that are created during the RENDER_PHASE of the portlet lifecycle.
setAttribute(ResponseStateManager.VIEW_STATE_PARAM, viewState);
}
}
}
// If specified in the WEB-INF/portlet.xml descriptor, then preserve the action parameters.
if (bridgeContext.isPreserveActionParams()) {
Map<String, String> actionRequestParameterMap = new HashMap<String, String>(
externalContext.getRequestParameterMap());
actionRequestParameterMap.remove(ResponseStateManager.VIEW_STATE_PARAM);
actionRequestParameterMap.remove(JAVAX_FACES_ENCODED_URL_PARAM);
setAttribute(BRIDGE_REQ_SCOPE_ATTR_ACTION_PARAMS, actionRequestParameterMap);
}
// Save the list of faces messages.
List<FacesMessageWrapper> facesMessageWrappers = new ArrayList<FacesMessageWrapper>();
Iterator<String> clientIds = facesContext.getClientIdsWithMessages();
while (clientIds.hasNext()) {
String clientId = clientIds.next();
Iterator<FacesMessage> facesMessages = facesContext.getMessages(clientId);
while (facesMessages.hasNext()) {
FacesMessage facesMessage = facesMessages.next();
FacesMessageWrapper facesMessageWrapper = new FacesMessageWrapper(clientId, facesMessage);
facesMessageWrappers.add(facesMessageWrapper);
}
}
if (facesMessageWrappers.size() > 0) {
setAttribute(BRIDGE_REQ_SCOPE_ATTR_FACES_MESSAGES, facesMessageWrappers);
}
else {
logger.trace("Not saving any faces messages");
}
// NOTE: PROPOSED-FOR-BRIDGE3-API: https://issues.apache.org/jira/browse/PORTLETBRIDGE-203 Build up a list
// of attributes found in the FacesContext attribute map and save them. It has to be copied in this manner
// because the Faces implementation likely calls the clear() method during the call to its
// FacesContextImpl.release() method.
saveJSF2FacesContextAttributes(facesContext);
boolean saveNonExcludedAttributes = true;
// If a redirect occurred, then indicate that the non-excluded request attributes are not to be preserved.
if (isRedirectOccurred()) {
// TCK TestPage062: eventScopeNotRestoredRedirectTest
logger.trace("Due to redirect, not saving any non-excluded request attributes");
saveNonExcludedAttributes = false;
}
// Otherwise, if the portlet mode has changed, then indicate that the non-exluded request attributes are
// not to be preserved.
else if (isPortletModeChanged()) {
logger.trace("Due to PortletMode change, not saving any non-excluded request attributes");
saveNonExcludedAttributes = false;
}
// If appropriate, save the non-excluded request attributes. This would include, for example, managed-bean
// instances that may have been created during the ACTION_PHASE that need to survive to the RENDER_PHASE.
Map<String, Object> currentRequestAttributes = externalContext.getRequestMap();
if (currentRequestAttributes != null) {
List<RequestAttribute> savedRequestAttributes = new ArrayList<RequestAttribute>();
List<String> nonExcludedAttributeNames = new ArrayList<String>();
Iterator<Map.Entry<String, Object>> itr = currentRequestAttributes.entrySet().iterator();
if (itr != null) {
while (itr.hasNext()) {
Map.Entry<String, Object> mapEntry = itr.next();
String attributeName = mapEntry.getKey();
Object attributeValue = mapEntry.getValue();
if (isExcludedRequestAttributeByConfig(attributeName, attributeValue) ||
isExcludedRequestAttributeByAnnotation(attributeValue) ||
isExcludedRequestAttributeByNamespace(attributeName) ||
isExcludedRequestAttributeByInstance(attributeName, attributeValue) ||
isExcludedRequestAttributeByPreExisting(attributeName)) {
logger.trace("NOT saving EXCLUDED attribute name=[{0}]", attributeName);
}
else {
if (saveNonExcludedAttributes) {
logger.trace("SAVING non-excluded request attribute name=[{0}] value=[{1}]",
attributeName, attributeValue);
savedRequestAttributes.add(new RequestAttribute(attributeName, attributeValue));
}
nonExcludedAttributeNames.add(attributeName);
}
}
if (savedRequestAttributes.size() > 0) {
setAttribute(BRIDGE_REQ_SCOPE_ATTR_REQUEST_ATTRIBUTES, savedRequestAttributes);
}
else {
logger.trace("Not saving any non-excluded request attributes");
}
setAttribute(BRIDGE_REQ_SCOPE_NON_EXCLUDED_ATTR_NAMES, nonExcludedAttributeNames);
}
}
else {
logger.trace("Not saving any non-excluded request attributes because there are no request attributes!");
}
}
// If running in the ACTION_PHASE or EVENT_PHASE, then the Flash scope must be saved as well so that it can be
// restored.
Bridge.PortletPhase portletRequestPhase = bridgeContext.getPortletRequestPhase();
if ((portletRequestPhase == Bridge.PortletPhase.ACTION_PHASE) ||
(portletRequestPhase == Bridge.PortletPhase.EVENT_PHASE)) {
// PROPOSED-FOR-JSR344-API: http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1070
// PROPOSED-FOR-BRIDGE3-API: https://issues.apache.org/jira/browse/PORTLETBRIDGE-201
saveFlashState(externalContext);
// PROPOSE-FOR-BRIDGE3-API
saveClientWindow(externalContext);
}
// If running in the ACTION_PHASE or EVENT_PHASE, then the incongruity context must be saved as well so that it
// can be restored.
if ((portletRequestPhase == Bridge.PortletPhase.ACTION_PHASE) ||
(portletRequestPhase == Bridge.PortletPhase.EVENT_PHASE)) {
IncongruityContext incongruityContext = bridgeContext.getIncongruityContext();
Map<String, Object> incongruityAttributeMap = incongruityContext.getAttributes();
int mapSize = incongruityAttributeMap.size();
List<IncongruityAttribute> savedIncongruityAttributes = new ArrayList<IncongruityAttribute>(mapSize);
Iterator<Map.Entry<String, Object>> itr = incongruityAttributeMap.entrySet().iterator();