Save This Page
Home » mojarra-1.2_09-b02-FCS-source » com.sun.faces.lifecycle » [javadoc | source]
    1   /*
    2    * $Id: RestoreViewPhase.java,v 1.51.4.2 2007/10/03 20:37:27 rlubke Exp $
    3    */
    4   
    5   /*
    6    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    7    * 
    8    * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
    9    * 
   10    * The contents of this file are subject to the terms of either the GNU
   11    * General Public License Version 2 only ("GPL") or the Common Development
   12    * and Distribution License("CDDL") (collectively, the "License").  You
   13    * may not use this file except in compliance with the License. You can obtain
   14    * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
   15    * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
   16    * language governing permissions and limitations under the License.
   17    * 
   18    * When distributing the software, include this License Header Notice in each
   19    * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
   20    * Sun designates this particular file as subject to the "Classpath" exception
   21    * as provided by Sun in the GPL Version 2 section of the License file that
   22    * accompanied this code.  If applicable, add the following below the License
   23    * Header, with the fields enclosed by brackets [] replaced by your own
   24    * identifying information: "Portions Copyrighted [year]
   25    * [name of copyright owner]"
   26    * 
   27    * Contributor(s):
   28    * 
   29    * If you wish your version of this file to be governed by only the CDDL or
   30    * only the GPL Version 2, indicate your decision by adding "[Contributor]
   31    * elects to include this software in this distribution under the [CDDL or GPL
   32    * Version 2] license."  If you don't indicate a single choice of license, a
   33    * recipient has the option to distribute your version of this file under
   34    * either the CDDL, the GPL Version 2 or to extend the choice of license to
   35    * its licensees as provided above.  However, if you add GPL Version 2 code
   36    * and therefore, elected the GPL Version 2 license, then the option applies
   37    * only if the new code is made subject to such option by the copyright
   38    * holder.
   39    */
   40   
   41   // RestoreViewPhase.java
   42   
   43   package com.sun.faces.lifecycle;
   44   
   45   import java.util.Iterator;
   46   import java.util.ListIterator;
   47   import java.util.Map;
   48   import java.util.logging.Level;
   49   import java.util.logging.Logger;
   50   
   51   import javax.el.ValueExpression;
   52   import javax.faces.FacesException;
   53   import javax.faces.application.ViewExpiredException;
   54   import javax.faces.application.ViewHandler;
   55   import javax.faces.component.UIComponent;
   56   import javax.faces.component.UIViewRoot;
   57   import javax.faces.context.FacesContext;
   58   import javax.faces.event.PhaseId;
   59   import javax.faces.event.PhaseListener;
   60   import javax.faces.lifecycle.Lifecycle;
   61   import javax.faces.render.ResponseStateManager;
   62   import javax.servlet.http.HttpServletRequest;
   63   
   64   import com.sun.faces.config.WebConfiguration;
   65   import com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter;
   66   import com.sun.faces.renderkit.RenderKitUtils;
   67   import com.sun.faces.util.DebugUtil;
   68   import com.sun.faces.util.FacesLogger;
   69   import com.sun.faces.util.MessageUtils;
   70   import com.sun.faces.util.Util;
   71   
   72   /**
   73    * <B>Lifetime And Scope</B> <P> Same lifetime and scope as
   74    * DefaultLifecycleImpl.
   75    *
   76    * @version $Id: RestoreViewPhase.java,v 1.51.4.2 2007/10/03 20:37:27 rlubke Exp $
   77    */
   78   
   79   public class RestoreViewPhase extends Phase {
   80   
   81       private static final String WEBAPP_ERROR_PAGE_MARKER =
   82               "javax.servlet.error.message";
   83   
   84       private static Logger LOGGER = FacesLogger.LIFECYCLE.getLogger();
   85   
   86       private WebConfiguration webConfig;
   87   
   88   
   89       // ---------------------------------------------------------- Public Methods
   90   
   91   
   92       public PhaseId getId() {
   93   
   94           return PhaseId.RESTORE_VIEW;
   95   
   96       }
   97   
   98   
   99       public void doPhase(FacesContext context,
  100                           Lifecycle lifecycle,
  101                           ListIterator<PhaseListener> listeners) {
  102   
  103           Util.getViewHandler(context).initView(context);
  104           super.doPhase(context, lifecycle, listeners);
  105   
  106       }
  107   
  108       /**
  109        * PRECONDITION: the necessary factories have been installed in the
  110        * ServletContext attr set. <P>
  111        * <p/>
  112        * POSTCONDITION: The facesContext has been initialized with a tree.
  113        */
  114   
  115       public void execute(FacesContext facesContext) throws FacesException {
  116   
  117           if (LOGGER.isLoggable(Level.FINE)) {
  118               LOGGER.fine("Entering RestoreViewPhase");
  119           }
  120           if (null == facesContext) {
  121               throw new FacesException(MessageUtils.getExceptionMessageString(
  122                     MessageUtils.NULL_CONTEXT_ERROR_MESSAGE_ID));
  123           }
  124   
  125           // If an app had explicitely set the tree in the context, use that;
  126           //
  127           UIViewRoot viewRoot = facesContext.getViewRoot();
  128           if (viewRoot != null) {
  129               if (LOGGER.isLoggable(Level.FINE)) {
  130                   LOGGER.fine("Found a pre created view in FacesContext");
  131               }
  132               facesContext.getViewRoot().setLocale(
  133                    facesContext.getExternalContext().getRequestLocale());
  134               doPerComponentActions(facesContext, viewRoot);
  135               if (!isPostback(facesContext)) {
  136                   facesContext.responseComplete();
  137               }
  138               return;
  139           }
  140   
  141           // Reconstitute or create the request tree
  142           Map requestMap = facesContext.getExternalContext().getRequestMap();
  143           String viewId = (String)
  144                 requestMap.get("javax.servlet.include.path_info");
  145           if (viewId == null) {
  146               viewId = facesContext.getExternalContext().getRequestPathInfo();
  147           }
  148   
  149           // It could be that this request was mapped using
  150           // a prefix mapping in which case there would be no
  151           // path_info.  Query the servlet path.
  152           if (viewId == null) {
  153               viewId = (String)
  154                     requestMap.get("javax.servlet.include.servlet_path");
  155           }
  156   
  157           if (viewId == null) {
  158               Object request = facesContext.getExternalContext().getRequest();
  159               if (request instanceof HttpServletRequest) {
  160                   viewId = ((HttpServletRequest) request).getServletPath();
  161               }
  162           }
  163   
  164           if (viewId == null) {
  165               if (LOGGER.isLoggable(Level.WARNING)) {
  166                   LOGGER.warning("viewId is null");
  167               }
  168               throw new FacesException(MessageUtils.getExceptionMessageString(
  169                     MessageUtils.NULL_REQUEST_VIEW_ERROR_MESSAGE_ID));
  170           }
  171   
  172           boolean isPostBack = (isPostback(facesContext) && !isErrorPage(facesContext));
  173           if (isPostBack) {
  174               // try to restore the view
  175               ViewHandler viewHandler = Util.getViewHandler(facesContext);
  176               viewRoot = viewHandler.restoreView(facesContext, viewId);
  177   
  178               if (viewRoot == null) {
  179                   if (is11CompatEnabled(facesContext)) {
  180                       // 1.1 -> create a new view and flag that the response should
  181                       //        be immediately rendered
  182                       viewRoot = viewHandler.createView(facesContext, viewId);
  183                       facesContext.renderResponse();
  184                   } else {
  185                       Object[] params = {viewId};
  186                       throw new ViewExpiredException(
  187                             MessageUtils.getExceptionMessageString(
  188                                   MessageUtils.RESTORE_VIEW_ERROR_MESSAGE_ID,
  189                                   params),
  190                             viewId);
  191                   }
  192               }
  193   
  194               facesContext.setViewRoot(viewRoot);
  195               doPerComponentActions(facesContext, viewRoot);
  196   
  197               if (LOGGER.isLoggable(Level.FINE)) {
  198                   LOGGER.fine("Postback: Restored view for " + viewId);
  199               }
  200           } else {
  201               if (LOGGER.isLoggable(Level.FINE)) {
  202                   LOGGER.fine("New request: creating a view for " + viewId);
  203               }
  204               // if that fails, create one
  205               viewRoot = (Util.getViewHandler(facesContext)).
  206                     createView(facesContext, viewId);
  207               facesContext.setViewRoot(viewRoot);
  208               facesContext.renderResponse();
  209           }
  210           assert(null != viewRoot);
  211   
  212           if (isPostBack && LOGGER.isLoggable(Level.FINEST)) {
  213               LOGGER.log(Level.FINEST, "+=+=+=+=+=+= Restored View Printout for " + viewId);
  214               DebugUtil.printTree(viewRoot, LOGGER, Level.FINEST);
  215           }
  216   
  217           if (LOGGER.isLoggable(Level.FINE)) {
  218               LOGGER.fine("Exiting RestoreViewPhase");
  219           }
  220   
  221       }
  222   
  223   
  224       // ------------------------------------------------------- Protected Methods
  225   
  226   
  227       /**
  228        * <p>Do any per-component actions necessary during reconstitute</p>
  229        * @param context the <code>FacesContext</code> for the current request
  230        * @param uic the <code>UIComponent</code> to process the
  231        *  <code>binding</code> attribute
  232        */
  233       protected void doPerComponentActions(FacesContext context,
  234                                            UIComponent uic) {
  235   
  236           // if this component has a component value reference expression,
  237           // make sure to populate the ValueExpression for it.
  238           ValueExpression valueExpression;
  239           if (null != (valueExpression = uic.getValueExpression("binding"))) {
  240               valueExpression.setValue(context.getELContext(), uic);
  241           }
  242   
  243           for (Iterator<UIComponent> kids =  uic.getFacetsAndChildren();
  244                kids.hasNext(); ) {
  245               doPerComponentActions(context, kids.next());
  246           }
  247   
  248       }
  249   
  250       // --------------------------------------------------------- Private Methods
  251   
  252   
  253       /**
  254        * @param context the <code>FacesContext</code> for the current request
  255        * @return <code>true</code> if the {@link ResponseStateManager#isPostback(javax.faces.context.FacesContext)}
  256        *  returns <code>true</code> <em>and</em> the request doesn't contain the
  257        *  attribute <code>javax.servlet.error.message</code> which indicates we've been
  258        *  forwarded to an error page.
  259        */
  260   
  261       private boolean isPostback(FacesContext context) {
  262   
  263           // Get the renderKitId by calling viewHandler.calculateRenderKitId().
  264           String renderkitId =
  265                 context.getApplication().getViewHandler().
  266                       calculateRenderKitId(context);
  267           ResponseStateManager rsm =
  268                 RenderKitUtils.getResponseStateManager(context,
  269                                                        renderkitId);
  270           return rsm.isPostback(context);
  271   
  272       }
  273   
  274   
  275       /**
  276        * The Servlet specification states that if an error occurs
  277        * in the application and there is a matching error-page declaration,
  278        * the that original request the cause the error is forwarded
  279        * to the error page.
  280        *
  281        * If the error occurred during a post-back and a matching
  282        * error-page definition was found, then an attempt to restore
  283        * the error view would be made as the javax.faces.ViewState
  284        * marker would still be in the request parameters.
  285        *
  286        * Use this method to determine if the current request is
  287        * an error page to avoid the above condition.
  288        *
  289        * @param context the FacesContext for the current request
  290        * @return <code>true</code> if <code>WEBAPP_ERROR_PAGE_MARKER</code>
  291        *  is found in the request, otherwise return <code>false</code>
  292        */
  293       private static boolean isErrorPage(FacesContext context) {
  294   
  295           return (context.getExternalContext().
  296                       getRequestMap().get(WEBAPP_ERROR_PAGE_MARKER) != null);
  297   
  298       }
  299   
  300   
  301       private WebConfiguration getWebConfig(FacesContext context) {
  302   
  303           if (webConfig == null) {
  304               webConfig = WebConfiguration.getInstance(context.getExternalContext());
  305           }
  306           return webConfig;
  307   
  308       }
  309   
  310       private boolean is11CompatEnabled(FacesContext context) {
  311   
  312           return (getWebConfig(context).isOptionEnabled(
  313                 BooleanWebContextInitParameter.EnableRestoreView11Compatibility));
  314           
  315       }
  316   
  317       // The testcase for this class is TestRestoreViewPhase.java
  318   
  319   } // end of class RestoreViewPhase

Save This Page
Home » mojarra-1.2_09-b02-FCS-source » com.sun.faces.lifecycle » [javadoc | source]