/** * <B>Lifetime And Scope</B> * * <p>Same lifetime and scope as DefaultLifecycleImpl. * * @version $Id: RestoreViewPhase.java,v 1.53.8.3 2008/04/12 16:32:30 edburns Exp $ */ public class RestoreViewPhase extends Phase { private static final String WEBAPP_ERROR_PAGE_MARKER = "javax.servlet.error.message"; private static Logger LOGGER = FacesLogger.LIFECYCLE.getLogger(); private WebConfiguration webConfig; // ---------------------------------------------------------- Public Methods public PhaseId getId() { return PhaseId.RESTORE_VIEW; } public void doPhase( FacesContext context, Lifecycle lifecycle, ListIterator<PhaseListener> listeners) { Util.getViewHandler(context).initView(context); super.doPhase(context, lifecycle, listeners); } /** * PRECONDITION: the necessary factories have been installed in the ServletContext attr set. * * <p> * * <p>POSTCONDITION: The facesContext has been initialized with a tree. */ public void execute(FacesContext facesContext) throws FacesException { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("Entering RestoreViewPhase"); } if (null == facesContext) { throw new FacesException( MessageUtils.getExceptionMessageString(MessageUtils.NULL_CONTEXT_ERROR_MESSAGE_ID)); } // If an app had explicitely set the tree in the context, use that; // UIViewRoot viewRoot = facesContext.getViewRoot(); if (viewRoot != null) { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("Found a pre created view in FacesContext"); } facesContext.getViewRoot().setLocale(facesContext.getExternalContext().getRequestLocale()); // do per-component actions UIViewRoot root = facesContext.getViewRoot(); final PostRestoreStateEvent event = new PostRestoreStateEvent(root); try { root.visitTree( VisitContext.createVisitContext(facesContext), new VisitCallback() { public VisitResult visit(VisitContext context, UIComponent target) { event.setComponent(target); target.processEvent(event); return VisitResult.ACCEPT; } }); } catch (AbortProcessingException e) { facesContext .getApplication() .publishEvent( ExceptionQueuedEvent.class, new ExceptionQueuedEventContext(facesContext, e)); } if (!facesContext.isPostback()) { facesContext.renderResponse(); } return; } // Reconstitute or create the request tree Map requestMap = facesContext.getExternalContext().getRequestMap(); String viewId = (String) requestMap.get("javax.servlet.include.path_info"); if (viewId == null) { viewId = facesContext.getExternalContext().getRequestPathInfo(); } // It could be that this request was mapped using // a prefix mapping in which case there would be no // path_info. Query the servlet path. if (viewId == null) { viewId = (String) requestMap.get("javax.servlet.include.servlet_path"); } if (viewId == null) { viewId = facesContext.getExternalContext().getRequestServletPath(); } if (viewId == null) { if (LOGGER.isLoggable(Level.WARNING)) { LOGGER.warning("viewId is null"); } throw new FacesException( MessageUtils.getExceptionMessageString(MessageUtils.NULL_REQUEST_VIEW_ERROR_MESSAGE_ID)); } ViewHandler viewHandler = Util.getViewHandler(facesContext); boolean isPostBack = (facesContext.isPostback() && !isErrorPage(facesContext)); if (isPostBack) { // try to restore the view viewRoot = viewHandler.restoreView(facesContext, viewId); if (viewRoot == null) { if (is11CompatEnabled(facesContext)) { // 1.1 -> create a new view and flag that the response should // be immediately rendered if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("Postback: recreating a view for " + viewId); } viewRoot = viewHandler.createView(facesContext, viewId); facesContext.renderResponse(); } else { Object[] params = {viewId}; throw new ViewExpiredException( MessageUtils.getExceptionMessageString( MessageUtils.RESTORE_VIEW_ERROR_MESSAGE_ID, params), viewId); } } facesContext.setViewRoot(viewRoot); if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("Postback: restored view for " + viewId); } } else { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("New request: creating a view for " + viewId); } ViewDeclarationLanguage vdl = facesContext .getApplication() .getViewHandler() .getViewDeclarationLanguage(facesContext, viewId); if (vdl != null) { // If we have one, get the ViewMetadata... ViewMetadata metadata = vdl.getViewMetadata(facesContext, viewId); if (metadata != null) { // perhaps it's not supported // and use it to create the ViewRoot. This will have, at most // the UIViewRoot and its metadata facet. viewRoot = metadata.createMetadataView(facesContext); // Only skip to render response if there are no view parameters Collection<UIViewParameter> params = ViewMetadata.getViewParameters(viewRoot); if (params.isEmpty()) { facesContext.renderResponse(); } } } else { facesContext.renderResponse(); } if (null == viewRoot) { viewRoot = (Util.getViewHandler(facesContext)).createView(facesContext, viewId); } facesContext.setViewRoot(viewRoot); assert (null != viewRoot); facesContext.getApplication().publishEvent(PostAddToViewEvent.class, viewRoot); } if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("Exiting RestoreViewPhase"); } } // --------------------------------------------------------- Private Methods /** * The Servlet specification states that if an error occurs in the application and there is a * matching error-page declaration, the that original request the cause the error is forwarded to * the error page. * * <p>If the error occurred during a post-back and a matching error-page definition was found, * then an attempt to restore the error view would be made as the javax.faces.ViewState marker * would still be in the request parameters. * * <p>Use this method to determine if the current request is an error page to avoid the above * condition. * * @param context the FacesContext for the current request * @return <code>true</code> if <code>WEBAPP_ERROR_PAGE_MARKER</code> is found in the request, * otherwise return <code>false</code> */ private static boolean isErrorPage(FacesContext context) { return (context.getExternalContext().getRequestMap().get(WEBAPP_ERROR_PAGE_MARKER) != null); } private WebConfiguration getWebConfig(FacesContext context) { if (webConfig == null) { webConfig = WebConfiguration.getInstance(context.getExternalContext()); } return webConfig; } private boolean is11CompatEnabled(FacesContext context) { return (getWebConfig(context) .isOptionEnabled(BooleanWebContextInitParameter.EnableRestoreView11Compatibility)); } // The testcase for this class is TestRestoreViewPhase.java } // end of class RestoreViewPhase
/** * <B>Lifetime And Scope</B> * * <p>Same lifetime and scope as DefaultLifecycleImpl. * * @version $Id: RenderResponsePhase.java,v 1.27 2007/12/17 21:46:09 rlubke Exp $ */ public class RenderResponsePhase extends Phase { // Log instance for this class private static Logger LOGGER = FacesLogger.LIFECYCLE.getLogger(); // ---------------------------------------------------------- Public Methods public void execute(FacesContext facesContext) throws FacesException { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("Entering RenderResponsePhase"); } if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("About to render view " + facesContext.getViewRoot().getViewId()); } // For requests intended to produce a partial response, we need prohibit // writing any content outside of the view itself (f:view). if (facesContext.isAjaxRequest()) { facesContext.enableResponseWriting(false); } try { // Setup message display LOGGER. if (LOGGER.isLoggable(Level.INFO)) { Iterator<String> clientIdIter = facesContext.getClientIdsWithMessages(); // If Messages are queued if (clientIdIter.hasNext()) { Set<String> clientIds = new HashSet<String>(); // Copy client ids to set of clientIds pending display. while (clientIdIter.hasNext()) { clientIds.add(clientIdIter.next()); } RequestStateManager.set( facesContext, RequestStateManager.CLIENT_ID_MESSAGES_NOT_DISPLAYED, clientIds); } } // render the view facesContext .getApplication() .getViewHandler() .renderView(facesContext, facesContext.getViewRoot()); // display results of message display LOGGER if (LOGGER.isLoggable(Level.INFO) && RequestStateManager.containsKey( facesContext, RequestStateManager.CLIENT_ID_MESSAGES_NOT_DISPLAYED)) { // remove so Set does not get modified when displaying messages. Set<String> clientIds = TypedCollections.dynamicallyCastSet( (Set) RequestStateManager.remove( facesContext, RequestStateManager.CLIENT_ID_MESSAGES_NOT_DISPLAYED), String.class); if (!clientIds.isEmpty()) { // Display each message possibly not displayed. StringBuilder builder = new StringBuilder(); for (String clientId : clientIds) { Iterator<FacesMessage> messages = facesContext.getMessages(clientId); while (messages.hasNext()) { FacesMessage message = messages.next(); builder.append("\n"); builder.append("sourceId=").append(clientId); builder.append("[severity=(").append(message.getSeverity()); builder.append("), summary=(").append(message.getSummary()); builder.append("), detail=(").append(message.getDetail()).append(")]"); } } LOGGER.log(Level.INFO, "jsf.non_displayed_message", builder.toString()); } } } catch (IOException e) { throw new FacesException(e.getMessage(), e); } if (LOGGER.isLoggable(Level.FINEST)) { LOGGER.log( Level.FINEST, "+=+=+=+=+=+= View structure printout for " + facesContext.getViewRoot().getViewId()); DebugUtil.printTree(facesContext.getViewRoot(), LOGGER, Level.FINEST); } if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("Exiting RenderResponsePhase"); } } public PhaseId getId() { return PhaseId.RENDER_RESPONSE; } // The testcase for this class is TestRenderResponsePhase.java } // end of class RenderResponsePhase
/** * <B>Lifetime And Scope</B> * * <p>Same lifetime and scope as DefaultLifecycleImpl. * * @version $Id: RenderResponsePhase.java,v 1.27 2007/12/17 21:46:09 rlubke Exp $ */ public class RenderResponsePhase extends Phase { // Log instance for this class private static Logger LOGGER = FacesLogger.LIFECYCLE.getLogger(); // ---------------------------------------------------------- Public Methods public void execute(FacesContext facesContext) throws FacesException { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("Entering RenderResponsePhase"); } if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("About to render view " + facesContext.getViewRoot().getViewId()); } // For requests intended to produce a partial response, we need prohibit // writing any content outside of the view itself (f:view). PartialViewContext partialViewContext = facesContext.getPartialViewContext(); if (partialViewContext.isAjaxRequest()) { OnOffResponseWrapper onOffResponse = new OnOffResponseWrapper(facesContext); onOffResponse.setEnabled(false); } try { ViewHandler vh = facesContext.getApplication().getViewHandler(); ViewDeclarationLanguage vdl = vh.getViewDeclarationLanguage(facesContext, facesContext.getViewRoot().getViewId()); if (vdl != null) { vdl.buildView(facesContext, facesContext.getViewRoot()); } boolean viewIdsUnchanged; do { String beforePublishViewId = facesContext.getViewRoot().getViewId(); // the before render event on the view root is a special case to keep door open for // navigation // this must be called *after* PDL.buildView() and before VH.renderView() facesContext .getApplication() .publishEvent(facesContext, PreRenderViewEvent.class, facesContext.getViewRoot()); String afterPublishViewId = facesContext.getViewRoot().getViewId(); viewIdsUnchanged = beforePublishViewId == null && afterPublishViewId == null || (beforePublishViewId != null && afterPublishViewId != null) && beforePublishViewId.equals(afterPublishViewId); } while (!viewIdsUnchanged); // render the view vh.renderView(facesContext, facesContext.getViewRoot()); } catch (IOException e) { throw new FacesException(e.getMessage(), e); } if (LOGGER.isLoggable(Level.FINEST)) { LOGGER.log( Level.FINEST, "+=+=+=+=+=+= View structure printout for " + facesContext.getViewRoot().getViewId()); DebugUtil.printTree(facesContext.getViewRoot(), LOGGER, Level.FINEST); } if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine("Exiting RenderResponsePhase"); } } public PhaseId getId() { return PhaseId.RENDER_RESPONSE; } // The testcase for this class is TestRenderResponsePhase.java } // end of class RenderResponsePhase