/** * Saves the state of the FacesContext as required by section 5.1.2 of the JSR 329 spec. This * method is designed to be called during the ACTION_PHASE of the portlet lifecycle. * * @param facesContext The current faces context. */ 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); } if ((beganInPhase == Bridge.PortletPhase.ACTION_PHASE) || (beganInPhase == Bridge.PortletPhase.EVENT_PHASE) || (beganInPhase == Bridge.PortletPhase.RESOURCE_PHASE)) { 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(facesContext); } // 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(); while (itr.hasNext()) { Map.Entry<String, Object> mapEntry = itr.next(); String name = mapEntry.getKey(); Object value = mapEntry.getValue(); logger.trace("Saving IncongruityContext attribute name=[{0}] value=[{1}]", name, value); savedIncongruityAttributes.add(new IncongruityAttribute(name, value)); } setAttribute( BRIDGE_REQ_SCOPE_ATTR_INCONGRUITY_CONTEXT_ATTRIBUTES, savedIncongruityAttributes); } }
@SuppressWarnings("unchecked") public void restoreState(FacesContext facesContext) { logger.debug("restoreState(facesContext)"); boolean restoreNonExcludedRequestAttributes = ((beganInPhase == Bridge.PortletPhase.ACTION_PHASE) || (beganInPhase == Bridge.PortletPhase.EVENT_PHASE) || (beganInPhase == Bridge.PortletPhase.RESOURCE_PHASE)); BridgeContext bridgeContext = BridgeContext.getCurrentInstance(); PortletPhase portletRequestPhase = bridgeContext.getPortletRequestPhase(); if (portletRequestPhase == Bridge.PortletPhase.RENDER_PHASE) { if (!portletMode.equals(bridgeContext.getPortletRequest().getPortletMode())) { setPortletModeChanged(true); restoreNonExcludedRequestAttributes = false; } } if ((beganInPhase == Bridge.PortletPhase.ACTION_PHASE) || (beganInPhase == Bridge.PortletPhase.EVENT_PHASE) || (beganInPhase == Bridge.PortletPhase.RESOURCE_PHASE)) { // Restore the view root that may have been saved during the ACTION_PHASE of the portlet // lifecycle. UIViewRoot uiViewRoot = (UIViewRoot) getAttribute(BRIDGE_REQ_SCOPE_ATTR_FACES_VIEW_ROOT); if (uiViewRoot != null) { facesContext.setViewRoot(uiViewRoot); logger.debug("Restored viewId=[{0}] uiViewRoot=[{1}]", uiViewRoot.getViewId(), uiViewRoot); } else { logger.debug("Did not restore uiViewRoot"); } // Restore the faces messages that may have been saved during the ACTION_PHASE of the portlet // lifecycle. List<FacesMessageWrapper> facesMessages = (List<FacesMessageWrapper>) getAttribute(BRIDGE_REQ_SCOPE_ATTR_FACES_MESSAGES); boolean restoredFacesMessages = false; if (facesMessages != null) { for (FacesMessageWrapper facesMessageWrapper : facesMessages) { String clientId = facesMessageWrapper.getClientId(); FacesMessage facesMessage = facesMessageWrapper.getFacesMessage(); facesContext.addMessage(clientId, facesMessage); logger.trace("Restored facesMessage=[{0}]", facesMessage.getSummary()); restoredFacesMessages = true; } } if (restoredFacesMessages) { logger.debug("Restored facesMessages"); } else { logger.debug("Did not restore any facesMessages"); } // NOTE: PROPOSE-FOR-BRIDGE3-API: https://issues.apache.org/jira/browse/PORTLETBRIDGE-203 // Restore the // FacesContext attributes that may have been saved during the ACTION_PHASE of the portlet // lifecycle. restoreJSF2FacesContextAttributes(facesContext); } if (restoreNonExcludedRequestAttributes) { // Restore the non-excluded request attributes. List<RequestAttribute> savedRequestAttributes = (List<RequestAttribute>) getAttribute(BRIDGE_REQ_SCOPE_ATTR_REQUEST_ATTRIBUTES); boolean restoredNonExcludedRequestAttributes = false; if (savedRequestAttributes != null) { Map<String, Object> currentRequestAttributes = facesContext.getExternalContext().getRequestMap(); // If a redirect did not occur, then restore the non-excluded request attributes. if (!isRedirectOccurred()) { for (RequestAttribute requestAttribute : savedRequestAttributes) { String name = requestAttribute.getName(); Object value = requestAttribute.getValue(); logger.trace( "Restoring non-excluded request attribute name=[{0}] value=[{1}]", name, value); currentRequestAttributes.put(name, value); restoredNonExcludedRequestAttributes = true; } } } if (restoredNonExcludedRequestAttributes) { logger.debug("Restored non-excluded request attributes"); } else { logger.debug("Did not restore any non-excluded request attributes"); } } // If running in the RENDER_PHASE, then the Flash scope must be restored. if (portletRequestPhase == Bridge.PortletPhase.RENDER_PHASE) { // NOTE: PROPOSED-FOR-BRIDGE3-API: https://issues.apache.org/jira/browse/PORTLETBRIDGE-201 // Restore the flash scope. restoreFlashState(facesContext); } // If running in the RENDER_PHASE, then the incongruity context must be restored. if (((beganInPhase == Bridge.PortletPhase.ACTION_PHASE) || (beganInPhase == Bridge.PortletPhase.EVENT_PHASE)) && (portletRequestPhase == Bridge.PortletPhase.RENDER_PHASE)) { List<IncongruityAttribute> savedIncongruityAttributes = (List<IncongruityAttribute>) getAttribute(BRIDGE_REQ_SCOPE_ATTR_INCONGRUITY_CONTEXT_ATTRIBUTES); if (savedIncongruityAttributes != null) { IncongruityContext incongruityContext = bridgeContext.getIncongruityContext(); Map<String, Object> incongruityContextAttributes = incongruityContext.getAttributes(); for (IncongruityAttribute incongruityAttribute : savedIncongruityAttributes) { String key = incongruityAttribute.getName(); Object value = incongruityAttribute.getValue(); incongruityContextAttributes.put(key, value); } } } }