All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.faces.application.view.JspViewHandlingStrategy Maven / Gradle / Ivy

Go to download

This is the master POM file for Oracle's Implementation of the JSF 2.2 Specification.

There is a newer version: 2.2.20
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package com.sun.faces.application.view;

import java.beans.BeanInfo;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.faces.FacesException;
import javax.faces.FactoryFinder;
import javax.faces.event.PostAddToViewEvent;
import javax.faces.view.ViewMetadata;
import javax.faces.application.Resource;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.RenderKit;
import javax.faces.render.RenderKitFactory;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.jstl.core.Config;

import com.sun.faces.application.ViewHandlerResponseWrapper;
import com.sun.faces.util.FacesLogger;
import com.sun.faces.util.MessageUtils;
import com.sun.faces.util.RequestStateManager;
import com.sun.faces.util.Util;

import javax.faces.view.StateManagementStrategy;

import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.ResponseBufferSize;

/**
 * This {@link ViewHandlingStrategy} handles JSP-based views.
 */
public class JspViewHandlingStrategy extends ViewHandlingStrategy {

    private static final Logger LOGGER = FacesLogger.APPLICATION.getLogger();
    private int responseBufferSize;


    // ------------------------------------------------------------ Constructors


    public JspViewHandlingStrategy() {

        try {
            responseBufferSize =
                  Integer.parseInt(webConfig.getOptionValue(ResponseBufferSize));
        } catch (NumberFormatException nfe) {
            responseBufferSize = Integer
                  .parseInt(ResponseBufferSize.getDefaultValue());
        }

    }



    // ------------------------------------ Methods from ViewDeclarationLanguage
    

    /**
     * 

* Not supported in JSP-based views. *

* * @see javax.faces.view.ViewDeclarationLanguage#getComponentMetadata(javax.faces.context.FacesContext, javax.faces.application.Resource) */ @Override public BeanInfo getComponentMetadata(FacesContext context, Resource componentResource) { throw new UnsupportedOperationException(); } /** *

* Not supported in JSP-based views. *

* * @see javax.faces.view.ViewDeclarationLanguage#getViewMetadata(javax.faces.context.FacesContext, String) */ @Override public ViewMetadata getViewMetadata(FacesContext context, String viewId) { return null; } /** *

* Not supported in JSP-based views. *

* * @see javax.faces.view.ViewDeclarationLanguage#getScriptComponentResource(javax.faces.context.FacesContext, javax.faces.application.Resource) */ @Override public Resource getScriptComponentResource(FacesContext context, Resource componentResource) { throw new UnsupportedOperationException(); } /** * @see javax.faces.view.ViewDeclarationLanguage#buildView(javax.faces.context.FacesContext, javax.faces.component.UIViewRoot) * @param context * @param view * @throws IOException */ public void buildView(FacesContext context, UIViewRoot view) throws IOException { if (Util.isViewPopulated(context, view)) { return; } try { if (executePageToBuildView(context, view)) { context.getExternalContext().responseFlushBuffer(); if (associate != null) { associate.responseRendered(); } context.responseComplete(); return; } } catch (IOException e) { throw new FacesException(e); } if (LOGGER.isLoggable(Level.FINE)) { LOGGER.log(Level.FINE, "Completed building view for : \n" + view.getViewId()); } context.getApplication().publishEvent(context, PostAddToViewEvent.class, UIViewRoot.class, view); Util.setViewPopulated(context, view); } /** * @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(); } @Override public StateManagementStrategy getStateManagementStrategy(FacesContext context, String viewId) { return null; } // --------------------------------------- Methods from ViewHandlingStrategy /** * This {@link ViewHandlingStrategy} should be the last one queried * and as such we return true. * * @see com.sun.faces.application.view.ViewHandlingStrategy#handlesViewId(String) */ @Override public boolean handlesViewId(String viewId) { return true; } @Override public String getId() { return JSP_VIEW_DECLARATION_LANGUAGE_ID; } // --------------------------------------------------------- Private Methods /** * 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 FacesContext for the current request * @param viewToExecute the view to build * @return true if the response should be immediately flushed * to the client, otherwise false * @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; } /** *

This is a separate method to account for handling the content * after the view tag.

* *

Create a new ResponseWriter around this response's Writer. * Set it into the FacesContext, saving the old one aside.

* *

call encodeBegin(), encodeChildren(), encodeEnd() on the * argument UIViewRoot.

* *

Restore the old ResponseWriter into the FacesContext.

* *

Write out the after view content to the response's writer.

* *

Flush the response buffer, and remove the after view content * from the request scope.

* * @param context the FacesContext for the current request * @param viewToRender the view to render * @throws java.io.IOException if an error occurs rendering the view to the client * @throws javax.faces.FacesException if some error occurs within the framework * processing */ private void doRenderView(FacesContext context, UIViewRoot viewToRender) throws IOException { if (null != associate) { associate.responseRendered(); } if (LOGGER.isLoggable(Level.FINE)) { LOGGER.log(Level.FINE, "About to render view " + viewToRender.getViewId()); } viewToRender.encodeAll(context); } /** *

* Simple utility method to wrap the current response with the * {@link ViewHandlerResponseWrapper}. *

* @param extContext the {@link ExternalContext} for this request * @return the current response wrapped with ViewHandlerResponseWrapper */ private static ViewHandlerResponseWrapper getWrapper(ExternalContext extContext) { Object response = extContext.getResponse(); if (response instanceof HttpServletResponse) { return new ViewHandlerResponseWrapper((HttpServletResponse) response); } throw new IllegalArgumentException(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy