Esempio n. 1
0
  /**
   * Inspects the incoming request parameters for the standardized state parameter name. In this
   * case, the parameter value will be the composite ID generated by
   * ServerSideStateHelper#writeState(FacesContext, Object, StringBuilder).
   *
   * <p>The composite key will be used to find the appropriate view within the session obtained from
   * the provided <code>FacesContext</code>
   */
  public Object getState(FacesContext ctx, String viewId) {

    String compoundId = getStateParamValue(ctx);

    if (compoundId == null) {
      return null;
    }

    if ("stateless".equals(compoundId)) {
      return "stateless";
    }

    int sep = compoundId.indexOf(':');
    assert (sep != -1);
    assert (sep < compoundId.length());

    String idInLogicalMap = compoundId.substring(0, sep);
    String idInActualMap = compoundId.substring(sep + 1);

    ExternalContext externalCtx = ctx.getExternalContext();
    Object sessionObj = externalCtx.getSession(false);

    // stop evaluating if the session is not available
    if (sessionObj == null) {
      if (LOGGER.isLoggable(Level.FINE)) {
        LOGGER.log(
            Level.FINE,
            "Unable to restore server side state for view ID {0} as no session is available",
            viewId);
      }
      return null;
    }

    //noinspection SynchronizationOnLocalVariableOrMethodParameter
    synchronized (sessionObj) {
      Map logicalMap = (Map) externalCtx.getSessionMap().get(LOGICAL_VIEW_MAP);
      if (logicalMap != null) {
        Map actualMap = (Map) logicalMap.get(idInLogicalMap);
        if (actualMap != null) {
          RequestStateManager.set(ctx, RequestStateManager.LOGICAL_VIEW_MAP, idInLogicalMap);
          Object[] state = (Object[]) actualMap.get(idInActualMap);
          Object[] restoredState = new Object[2];

          restoredState[0] = state[0];
          restoredState[1] = state[1];

          if (state != null) {
            RequestStateManager.set(ctx, RequestStateManager.ACTUAL_VIEW_MAP, idInActualMap);
            if (state.length == 2 && state[1] != null) {
              restoredState[1] = handleRestoreState(state[1]);
            }
          }

          return restoredState;
        }
      }
    }

    return null;
  }
  //
  // Methods from FacesContextFactory
  //
  public FacesContext getFacesContext(
      Object sc, Object request, Object response, Lifecycle lifecycle) throws FacesException {

    try {
      Util.parameterNonNull(sc);
      Util.parameterNonNull(request);
      Util.parameterNonNull(response);
      Util.parameterNonNull(lifecycle);
    } catch (Exception e) {
      throw new NullPointerException(
          MessageUtils.getExceptionMessageString(
              MessageUtils.FACES_CONTEXT_CONSTRUCTION_ERROR_MESSAGE_ID));
    }
    FacesContext ctx =
        new FacesContextImpl(
            new ExternalContextImpl(
                (ServletContext) sc, (ServletRequest) request, (ServletResponse) response),
            lifecycle);
    // store the default FacesContext and ExternalContext implementations
    // in the request so that the API can delegate if the happen to be
    // decorated by 1.1 implementations
    RequestStateManager.set(ctx, RequestStateManager.FACESCONTEXT_IMPL_ATTR_NAME, ctx);
    RequestStateManager.set(
        ctx, RequestStateManager.EXTERNALCONTEXT_IMPL_ATTR_NAME, ctx.getExternalContext());
    return ctx;
  }
Esempio n. 3
0
  /**
   * Obtain and return the {@link ResponseStateManager} for the specified #renderKitId.
   *
   * @param context the {@link FacesContext} of the current request
   * @param renderKitId {@link RenderKit} ID
   * @return the {@link ResponseStateManager} for the specified #renderKitId
   * @throws FacesException if an exception occurs while trying to obtain the <code>
   *     ResponseStateManager</code>
   */
  public static ResponseStateManager getResponseStateManager(
      FacesContext context, String renderKitId) throws FacesException {

    assert (null != renderKitId);
    assert (null != context);

    RenderKit renderKit = context.getRenderKit();
    if (renderKit == null) {
      // check request scope for a RenderKitFactory implementation
      RenderKitFactory factory =
          (RenderKitFactory)
              RequestStateManager.get(context, RequestStateManager.RENDER_KIT_IMPL_REQ);
      if (factory != null) {
        renderKit = factory.getRenderKit(context, renderKitId);
      } else {
        factory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
        if (factory == null) {
          throw new IllegalStateException();
        } else {
          RequestStateManager.set(context, RequestStateManager.RENDER_KIT_IMPL_REQ, factory);
        }
        renderKit = factory.getRenderKit(context, renderKitId);
      }
    }
    return renderKit.getResponseStateManager();
  }
Esempio n. 4
0
  /**
   * @return Stack of UIComponentClassicTagBase instances, each of which is a "view" tag. The bottom
   *     most element on the stack is the ViewTag itself. Subsequent instances are SubviewTag
   *     instances.
   */
  static Stack<UIComponentClassicTagBase> getViewTagStack() {

    FacesContext ctx = FacesContext.getCurrentInstance();
    //noinspection unchecked
    Stack<UIComponentClassicTagBase> result =
        (Stack<UIComponentClassicTagBase>)
            RequestStateManager.get(ctx, RequestStateManager.VIEWTAG_STACK_ATTR_NAME);
    if (result == null) {
      result = new Stack<UIComponentClassicTagBase>();
      RequestStateManager.set(ctx, RequestStateManager.VIEWTAG_STACK_ATTR_NAME, result);
    }

    return result;
  }
Esempio n. 5
0
  /**
   * @see {@link javax.faces.render.ResponseStateManager#getState(javax.faces.context.FacesContext,
   *     String)}
   */
  @Override
  public Object getState(FacesContext context, String viewId) {

    Object state = RequestStateManager.get(context, RequestStateManager.FACES_VIEW_STATE);
    if (state == null) {
      try {
        state = helper.getState(context, viewId);
        if (state != null) {
          RequestStateManager.set(context, RequestStateManager.FACES_VIEW_STATE, state);
        }
      } catch (IOException e) {
        throw new FacesException(e);
      }
    }
    return state;
  }
Esempio n. 6
0
  /**
   * Build the view.
   *
   * @param ctx the {@link FacesContext} for the current request
   * @param view the {@link UIViewRoot} to populate based of the Facelet template
   * @throws IOException if an error occurs building the view.
   */
  @Override
  public void buildView(FacesContext ctx, UIViewRoot view) throws IOException {

    if (Util.isViewPopulated(ctx, view)) {
      return;
    }
    updateStateSavingType(ctx, view.getViewId());
    view.setViewId(view.getViewId());

    if (LOGGER.isLoggable(Level.FINE)) {
      LOGGER.fine("Building View: " + view.getViewId());
    }
    if (faceletFactory == null) {
      ApplicationAssociate associate = ApplicationAssociate.getInstance(ctx.getExternalContext());
      faceletFactory = associate.getFaceletFactory();
      assert (faceletFactory != null);
    }
    RequestStateManager.set(ctx, RequestStateManager.FACELET_FACTORY, faceletFactory);
    Facelet f = faceletFactory.getFacelet(view.getViewId());

    // populate UIViewRoot
    f.apply(ctx, view);
    doPostBuildActions(view);
    Util.setViewPopulated(ctx, view);
  }
Esempio n. 7
0
  private void applyCompositeComponent(FaceletContext ctx, UIComponent c) throws IOException {

    FacesContext facesContext = ctx.getFacesContext();
    FaceletFactory factory =
        (FaceletFactory) RequestStateManager.get(facesContext, RequestStateManager.FACELET_FACTORY);
    VariableMapper orig = ctx.getVariableMapper();

    UIPanel facetComponent;
    if (ComponentHandler.isNew(c)) {
      facetComponent = (UIPanel) facesContext.getApplication().createComponent("javax.faces.Panel");
      facetComponent.setRendererType("javax.faces.Group");
      c.getFacets().put(UIComponent.COMPOSITE_FACET_NAME, facetComponent);
    } else {
      facetComponent = (UIPanel) c.getFacets().get(UIComponent.COMPOSITE_FACET_NAME);
    }
    assert (null != facetComponent);

    try {
      Facelet f = factory.getFacelet(ccResource.getURL());

      VariableMapper wrapper =
          new VariableMapperWrapper(orig) {

            @Override
            public ValueExpression resolveVariable(String variable) {
              return super.resolveVariable(variable);
            }
          };
      ctx.setVariableMapper(wrapper);
      f.apply(facesContext, facetComponent);
    } finally {
      ctx.setVariableMapper(orig);
    }
  }
  @Override
  @SuppressWarnings("deprecation")
  public Object getValue(ELContext context, Object base, Object property) throws ELException {

    // Don't call into the chain unless it's been decorated.
    if (legacyVR instanceof ChainAwareVariableResolver) {
      return null;
    }

    if (base != null) {
      return null;
    }
    if (base == null && property == null) {
      String message =
          MessageUtils.getExceptionMessageString(
              MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "base and property"); // ?????
      throw new PropertyNotFoundException(message);
    }
    context.setPropertyResolved(true);
    Object result = null;

    FacesContext facesContext = (FacesContext) context.getContext(FacesContext.class);
    String propString = property.toString();
    Map<String, Object> stateMap = RequestStateManager.getStateMap(facesContext);
    try {
      // If we are already in the midst of an expression evaluation
      // that touched this resolver...
      //noinspection unchecked
      List<String> varNames = (List<String>) stateMap.get(RequestStateManager.REENTRANT_GUARD);
      if (varNames != null && !varNames.isEmpty() && varNames.contains(propString)) {
        // take no action and return.
        context.setPropertyResolved(false);
        return null;
      }
      // Make sure subsequent calls don't take action.
      if (varNames == null) {
        varNames = new ArrayList<>();
        stateMap.put(RequestStateManager.REENTRANT_GUARD, varNames);
      }
      varNames.add(propString);

      result = legacyVR.resolveVariable(facesContext, propString);
    } catch (EvaluationException ex) {
      context.setPropertyResolved(false);
      throw new ELException(ex);
    } finally {
      // Make sure to remove the guard after the call returns
      //noinspection unchecked
      List<String> varNames = (List<String>) stateMap.get(RequestStateManager.REENTRANT_GUARD);
      if (varNames != null && !varNames.isEmpty()) {
        varNames.remove(propString);
      }
      // Make sure that the ELContext "resolved" indicator is set
      // in accordance wth the result of the resolution.
      context.setPropertyResolved(result != null);
    }
    return result;
  }
Esempio n. 9
0
  @Override
  public BeanInfo getComponentMetadata(FacesContext context, Resource ccResource) {
    // PENDING this implementation is terribly wasteful.
    // Must find a better way.
    CompositeComponentBeanInfo result;
    FaceletContext ctx =
        (FaceletContext) context.getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
    FaceletFactory factory =
        (FaceletFactory) RequestStateManager.get(context, RequestStateManager.FACELET_FACTORY);
    VariableMapper orig = ctx.getVariableMapper();
    UIComponent tmp = context.getApplication().createComponent("javax.faces.NamingContainer");
    UIPanel facetComponent =
        (UIPanel) context.getApplication().createComponent("javax.faces.Panel");
    facetComponent.setRendererType("javax.faces.Group");
    tmp.getFacets().put(UIComponent.COMPOSITE_FACET_NAME, facetComponent);
    // We have to put the resource in here just so the classes that eventually
    // get called by facelets have access to it.
    tmp.getAttributes().put(Resource.COMPONENT_RESOURCE_KEY, ccResource);

    Facelet f;

    try {
      f = factory.getFacelet(ccResource.getURL());
      VariableMapper wrapper =
          new VariableMapperWrapper(orig) {

            @Override
            public ValueExpression resolveVariable(String variable) {
              return super.resolveVariable(variable);
            }
          };
      ctx.setVariableMapper(wrapper);
      context.getAttributes().put(IS_BUILDING_METADATA, Boolean.TRUE);
      f.apply(context, facetComponent);
    } catch (Exception e) {
      if (e instanceof FacesException) {
        throw (FacesException) e;
      } else {
        throw new FacesException(e);
      }
    } finally {
      context.getAttributes().remove(IS_BUILDING_METADATA);
      ctx.setVariableMapper(orig);
    }
    result = (CompositeComponentBeanInfo) tmp.getAttributes().get(UIComponent.BEANINFO_KEY);

    return result;
  }
Esempio n. 10
0
  /** See the class javadocs. */
  public Object resolveVariable(FacesContext context, String name) throws EvaluationException {
    Object result = null;
    ELResolverChainType type = null;
    Object valueObject =
        RequestStateManager.get(context, RequestStateManager.EL_RESOLVER_CHAIN_TYPE_NAME);
    if (null != valueObject && valueObject instanceof ELResolverChainType) {
      type = (ELResolverChainType) valueObject;
    }
    if (ELResolverChainType.JSP == type) {
      ValueExpression ve =
          context
              .getApplication()
              .getExpressionFactory()
              .createValueExpression(context.getELContext(), "#{" + name + "}", Object.class);
      result = ve.getValue(context.getELContext());
    } else if (ELResolverChainType.Faces == type) {
      ELResolver elr = context.getApplication().getELResolver();
      result = elr.getValue(context.getELContext(), null, name);
    }

    return result;
  }
Esempio n. 11
0
  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");
    }
  }
Esempio n. 12
0
  /**
   * <p>
   * Stores the provided state within the session obtained from the provided
   * <code>FacesContext</code>
   * </p>
   *
   * <p>If <code>stateCapture</code> is <code>null</code>, the composite
   * key used to look up the actual and logical views will be written to
   * the client as a hidden field using the <code>ResponseWriter</code>
   * from the provided <code>FacesContext</code>.</p>
   *
   * <p>If <code>stateCapture</code> is not <code>null</code>, the composite
   * key will be appended to the <code>StringBuilder<code> without any markup
   * included or any content written to the client.
   */
  public void writeState(FacesContext ctx, Object state, StringBuilder stateCapture)
      throws IOException {

    Util.notNull("context", ctx);

    String id;

    UIViewRoot viewRoot = ctx.getViewRoot();

    if (!viewRoot.isTransient()) {
      if (!ctx.getAttributes().containsKey("com.sun.faces.ViewStateValue")) {
        Util.notNull("state", state);
        Object[] stateToWrite = (Object[]) state;
        ExternalContext externalContext = ctx.getExternalContext();
        Object sessionObj = externalContext.getSession(true);
        Map<String, Object> sessionMap = externalContext.getSessionMap();

        //noinspection SynchronizationOnLocalVariableOrMethodParameter
        synchronized (sessionObj) {
          Map<String, Map> logicalMap =
              TypedCollections.dynamicallyCastMap(
                  (Map) sessionMap.get(LOGICAL_VIEW_MAP), String.class, Map.class);
          if (logicalMap == null) {
            logicalMap = Collections.synchronizedMap(new LRUMap<String, Map>(numberOfLogicalViews));
            sessionMap.put(LOGICAL_VIEW_MAP, logicalMap);
          }

          Object structure = stateToWrite[0];
          Object savedState = handleSaveState(stateToWrite[1]);

          String idInLogicalMap =
              (String) RequestStateManager.get(ctx, RequestStateManager.LOGICAL_VIEW_MAP);
          if (idInLogicalMap == null) {
            idInLogicalMap =
                ((generateUniqueStateIds) ? createRandomId() : createIncrementalRequestId(ctx));
          }
          String idInActualMap = null;
          if (ctx.getPartialViewContext().isPartialRequest()) {
            // If partial request, do not change actual view Id, because page not actually changed.
            // Otherwise partial requests will soon overflow cache with values that would be never
            // used.
            idInActualMap =
                (String) RequestStateManager.get(ctx, RequestStateManager.ACTUAL_VIEW_MAP);
          }
          if (null == idInActualMap) {
            idInActualMap =
                ((generateUniqueStateIds) ? createRandomId() : createIncrementalRequestId(ctx));
          }
          Map<String, Object[]> actualMap =
              TypedCollections.dynamicallyCastMap(
                  logicalMap.get(idInLogicalMap), String.class, Object[].class);
          if (actualMap == null) {
            actualMap = new LRUMap<String, Object[]>(numberOfViews);
            logicalMap.put(idInLogicalMap, actualMap);
          }

          id = idInLogicalMap + ':' + idInActualMap;

          Object[] stateArray = actualMap.get(idInActualMap);
          // reuse the array if possible
          if (stateArray != null) {
            stateArray[0] = structure;
            stateArray[1] = savedState;
          } else {
            actualMap.put(idInActualMap, new Object[] {structure, savedState});
          }

          // always call put/setAttribute as we may be in a clustered environment.
          sessionMap.put(LOGICAL_VIEW_MAP, logicalMap);
          ctx.getAttributes().put("com.sun.faces.ViewStateValue", id);
        }
      } else {
        id = (String) ctx.getAttributes().get("com.sun.faces.ViewStateValue");
      }
    } else {
      id = "stateless";
    }

    if (stateCapture != null) {
      stateCapture.append(id);
    } else {
      ResponseWriter writer = ctx.getResponseWriter();

      writer.startElement("input", null);
      writer.writeAttribute("type", "hidden", null);

      String viewStateParam = ResponseStateManager.VIEW_STATE_PARAM;

      if ((namespaceParameters) && (viewRoot instanceof NamingContainer)) {
        String namingContainerId = viewRoot.getContainerClientId(ctx);
        if (namingContainerId != null) {
          viewStateParam = namingContainerId + viewStateParam;
        }
      }
      writer.writeAttribute("name", viewStateParam, null);
      if (webConfig.isOptionEnabled(EnableViewStateIdRendering)) {
        String viewStateId = Util.getViewStateId(ctx);
        writer.writeAttribute("id", viewStateId, null);
      }
      writer.writeAttribute("value", id, null);
      if (webConfig.isOptionEnabled(AutoCompleteOffOnViewState)) {
        writer.writeAttribute("autocomplete", "off", null);
      }
      writer.endElement("input");

      writeClientWindowField(ctx, writer);
      writeRenderKitIdField(ctx, writer);
    }
  }
Esempio n. 13
0
  /**
   * Execute the target view. If the HTTP status code range is not 2xx, then return true to indicate
   * the response should be immediately flushed by the caller so that conditions such as 404 are
   * properly handled.
   *
   * @param context the <code>FacesContext</code> for the current request
   * @param viewToExecute the view to build
   * @return <code>true</code> if the response should be immediately flushed to the client,
   *     otherwise <code>false</code>
   * @throws java.io.IOException if an error occurs executing the page
   */
  private boolean executePageToBuildView(FacesContext context, UIViewRoot viewToExecute)
      throws IOException {

    if (null == context) {
      String message =
          MessageUtils.getExceptionMessageString(
              MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "context");
      throw new NullPointerException(message);
    }
    if (null == viewToExecute) {
      String message =
          MessageUtils.getExceptionMessageString(
              MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "viewToExecute");
      throw new NullPointerException(message);
    }

    ExternalContext extContext = context.getExternalContext();

    if ("/*".equals(RequestStateManager.get(context, RequestStateManager.INVOCATION_PATH))) {
      throw new FacesException(
          MessageUtils.getExceptionMessageString(MessageUtils.FACES_SERVLET_MAPPING_INCORRECT_ID));
    }

    String requestURI = viewToExecute.getViewId();

    if (LOGGER.isLoggable(Level.FINE)) {
      LOGGER.fine("About to execute view " + requestURI);
    }

    // update the JSTL locale attribute in request scope so that JSTL
    // picks up the locale from viewRoot. This attribute must be updated
    // before the JSTL setBundle tag is called because that is when the
    // new LocalizationContext object is created based on the locale.
    if (extContext.getRequest() instanceof ServletRequest) {
      Config.set(
          (ServletRequest) extContext.getRequest(),
          Config.FMT_LOCALE,
          context.getViewRoot().getLocale());
    }
    if (LOGGER.isLoggable(Level.FINE)) {
      LOGGER.fine("Before dispacthMessage to viewId " + requestURI);
    }

    // save the original response
    Object originalResponse = extContext.getResponse();

    // replace the response with our wrapper
    ViewHandlerResponseWrapper wrapped = getWrapper(extContext);
    extContext.setResponse(wrapped);

    try {

      // build the view by executing the page
      extContext.dispatch(requestURI);

      if (LOGGER.isLoggable(Level.FINE)) {
        LOGGER.fine("After dispacthMessage to viewId " + requestURI);
      }
    } finally {
      // replace the original response
      extContext.setResponse(originalResponse);
    }

    // Follow the JSTL 1.2 spec, section 7.4,
    // on handling status codes on a forward
    if (wrapped.getStatus() < 200 || wrapped.getStatus() > 299) {
      // flush the contents of the wrapper to the response
      // this is necessary as the user may be using a custom
      // error page - this content should be propagated
      wrapped.flushContentToWrappedResponse();
      return true;
    }

    // Put the AFTER_VIEW_CONTENT into request scope
    // temporarily
    RequestStateManager.set(context, RequestStateManager.AFTER_VIEW_CONTENT, wrapped);

    return false;
  }
Esempio n. 14
0
  /**
   * @see javax.faces.view.ViewDeclarationLanguage#renderView(javax.faces.context.FacesContext,
   *     javax.faces.component.UIViewRoot)
   */
  public void renderView(FacesContext context, UIViewRoot view) throws IOException {

    // suppress rendering if "rendered" property on the component is
    // false
    if (!view.isRendered() || context.getResponseComplete()) {
      return;
    }

    ExternalContext extContext = context.getExternalContext();

    if (!Util.isViewPopulated(context, view)) {
      buildView(context, view);
    }

    // set up the ResponseWriter

    RenderKitFactory renderFactory =
        (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
    RenderKit renderKit = renderFactory.getRenderKit(context, view.getRenderKitId());

    ResponseWriter oldWriter = context.getResponseWriter();

    WriteBehindStateWriter stateWriter =
        new WriteBehindStateWriter(
            extContext.getResponseOutputWriter(), context, responseBufferSize);
    ResponseWriter newWriter;
    if (null != oldWriter) {
      newWriter = oldWriter.cloneWithWriter(stateWriter);
    } else {
      newWriter =
          renderKit.createResponseWriter(
              stateWriter, null, extContext.getRequestCharacterEncoding());
    }
    context.setResponseWriter(newWriter);

    //  Don't call startDoc and endDoc on a partial response
    if (context.getPartialViewContext().isPartialRequest()) {
      doRenderView(context, view);
      try {
        extContext.getFlash().doPostPhaseActions(context);
      } catch (UnsupportedOperationException uoe) {
        if (LOGGER.isLoggable(Level.FINE)) {
          LOGGER.fine(
              "ExternalContext.getFlash() throw UnsupportedOperationException -> Flash unavailable");
        }
      }
    } else {
      // render the view to the response
      newWriter.startDocument();
      doRenderView(context, view);
      try {
        extContext.getFlash().doPostPhaseActions(context);
      } catch (UnsupportedOperationException uoe) {
        if (LOGGER.isLoggable(Level.FINE)) {
          LOGGER.fine(
              "ExternalContext.getFlash() throw UnsupportedOperationException -> Flash unavailable");
        }
      }
      newWriter.endDocument();
    }

    // replace markers in the body content and write it to response.

    // flush directly to the response
    if (stateWriter.stateWritten()) {
      stateWriter.flushToWriter();
    }

    // clear the ThreadLocal reference.
    stateWriter.release();

    if (null != oldWriter) {
      context.setResponseWriter(oldWriter);
    }

    // write any AFTER_VIEW_CONTENT to the response
    // side effect: AFTER_VIEW_CONTENT removed
    ViewHandlerResponseWrapper wrapper =
        (ViewHandlerResponseWrapper)
            RequestStateManager.remove(context, RequestStateManager.AFTER_VIEW_CONTENT);
    if (null != wrapper) {
      wrapper.flushToWriter(
          extContext.getResponseOutputWriter(), extContext.getResponseCharacterEncoding());
    }

    extContext.responseFlushBuffer();
  }