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

jakarta.faces.render.ResponseStateManager Maven / Gradle / Ivy

There is a newer version: 4.1.1
Show newest version
/*
 * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package jakarta.faces.render;

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

import jakarta.faces.application.StateManager;
import jakarta.faces.application.StateManager.SerializedView;
import jakarta.faces.context.FacesContext;
import jakarta.faces.context.ResponseWriter;

/**
 * 

* ResponseStateManager is the helper class to * {@link jakarta.faces.application.StateManager} that knows the specific rendering technology being used to generate * the response. It is a singleton abstract class, vended by the {@link RenderKit}. This class knows the mechanics of * saving state, whether it be in hidden fields, session, or some combination of the two. *

*/ public abstract class ResponseStateManager { private static Logger log = Logger.getLogger("jakarta.faces.render"); /** *

* The name of the request parameter used by the default implementation of * {@link jakarta.faces.application.ViewHandler#calculateRenderKitId} to derive a RenderKit ID. *

*/ public static final String RENDER_KIT_ID_PARAM = "jakarta.faces.RenderKitId"; /** *

* Implementations must use this constant field value as * the name of the client parameter in which to save the state between requests. The * id attribute must be a concatenation of the return from * {@link jakarta.faces.component.UIViewRoot#getContainerClientId}, the return from * {@link jakarta.faces.component.UINamingContainer#getSeparatorChar}, this constant field value, the separator char, * and a number that is guaranteed to be unique with respect to all the other instances of this kind of client parameter * in the view. *

* *

* It is strongly recommend that implementations guard against cross site scripting attacks by at least making the value * of this parameter difficult to predict. *

* * @since 1.2 */ public static final String VIEW_STATE_PARAM = "jakarta.faces.ViewState"; /** *

* The name of the hidden field that refers to the encoded ClientWindow. This field is only used if * {@link jakarta.faces.lifecycle.ClientWindow#CLIENT_WINDOW_MODE_PARAM_NAME} is not "none". The id * attribute must be a concatenation of the return from {@link jakarta.faces.component.UIViewRoot#getContainerClientId}, * the return from {@link jakarta.faces.component.UINamingContainer#getSeparatorChar}, this constant field value, the * separator char, and a number that is guaranteed to be unique with respect to all the other instances of this kind of * client parameter in the view. The value of this parameter is the return from * {@link jakarta.faces.lifecycle.ClientWindow#getId}. *

* * @since 2.2 * */ public static final String CLIENT_WINDOW_PARAM = "jakarta.faces.ClientWindow"; /** *

* The name of the URL query parameter for transmitting the client window id. This parameter is only used if * {@link jakarta.faces.lifecycle.ClientWindow#CLIENT_WINDOW_MODE_PARAM_NAME} is not "none". The name of the parameter * is given by the constant value of this field. The value of this parameter is the return from * {@link jakarta.faces.lifecycle.ClientWindow#getId}. *

* * @since 2.2 */ public static final String CLIENT_WINDOW_URL_PARAM = "jfwid"; /** *

* The value of this constant is taken to be the name of a request parameter whose value is inspected to verify the * safety of an incoming non-postback request with respect to the currently configured Set of protected * views for this application. *

* * @since 2.2 */ public static final String NON_POSTBACK_VIEW_TOKEN_PARAM = "jakarta.faces.Token"; /** *

* Take the argument state and write it into the output using the * current {@link ResponseWriter}, which must be correctly positioned already. *

* *

* Call {@link FacesContext#getViewRoot()}. If {@link jakarta.faces.component.UIComponent#isTransient()} returns * {@code true}, take implementation specific action so that the following call to {@link #isStateless} returns * {@code true} and return. Otherwise, proceed as follows. *

* *

* If the state is to be written out to hidden fields, the implementation must take care to make all necessary character * replacements to make the Strings suitable for inclusion as an HTTP request paramater. *

* *

* If the state saving method for this application is * {@link jakarta.faces.application.StateManager#STATE_SAVING_METHOD_CLIENT}, the implementation * must encrypt the state to be saved to the client * in a tamper evident manner. *

* *

* If the state saving method for this application is * {@link jakarta.faces.application.StateManager#STATE_SAVING_METHOD_SERVER}, and the current request is an * Ajax request {@link jakarta.faces.context.PartialViewContext#isAjaxRequest} returns true), * use the current view state identifier if it is available (do not generate a new identifier). *

* *

* Write out the render kit identifier associated with this ResponseStateManager implementation with the * name as the value of the String constant ResponseStateManager.RENDER_KIT_ID_PARAM. The * render kit identifier must not be written if: *

*
    *
  • it is the default render kit identifier as returned by * {@link jakarta.faces.application.Application#getDefaultRenderKitId()} or
  • *
  • the render kit identfier is the value of jakarta.faces.render.RenderKitFactory.HTML_BASIC_RENDER_KIT * and {@link jakarta.faces.application.Application#getDefaultRenderKitId()} returns null.
  • *
* *

* For backwards compatability with existing ResponseStateManager implementations, the default * implementation of this method checks if the argument is an instance of SerializedView. If so, it calls * through to * {@link #writeState(jakarta.faces.context.FacesContext,jakarta.faces.application.StateManager.SerializedView)}. If * not, it expects the state to be a two element Object array. It creates an instance of SerializedView and * stores the state as the treeStructure, and passes it to * {@link #writeState(jakarta.faces.context.FacesContext,jakarta.faces.application.StateManager.SerializedView)}. *

* *

* The {@link jakarta.faces.lifecycle.ClientWindow} must be written using these steps. Call * {@link jakarta.faces.context.ExternalContext#getClientWindow}. If the result is null, take no further * action regarding the ClientWindow. If the result is non-null, write a hidden field whose * name is {@link #CLIENT_WINDOW_PARAM} and whose id is * <VIEW_ROOT_CONTAINER_CLIENT_ID><SEP>jakarta.faces.ClientWindow<SEP><UNIQUE_PER_VIEW_NUMBER> * where <SEP> is the currently configured UINamingContainer.getSeparatorChar(). * <VIEW_ROOT_CONTAINER_CLIENT_ID> is the return from UIViewRoot.getContainerClientId() on the view * from whence this state originated. <UNIQUE_PER_VIEW_NUMBER> is a number that must be unique within this view, * but must not be included in the view state. The value of the field is implementation dependent but must uniquely * identify this window within the user's session. *

* * * @since 1.2 * * @param context The {@link FacesContext} instance for the current request * @param state The serialized state information previously saved * @throws IOException if the state argument is not an array of length 2. * */ public void writeState(FacesContext context, Object state) throws IOException { SerializedView view; if (state instanceof SerializedView) { view = (SerializedView) state; } else { if (state instanceof Object[]) { Object[] stateArray = (Object[]) state; if (2 == stateArray.length) { StateManager stateManager = context.getApplication().getStateManager(); view = stateManager.new SerializedView(stateArray[0], stateArray[1]); } else { // PENDING - I18N if (log.isLoggable(Level.SEVERE)) { log.log(Level.SEVERE, "State is not an expected array of length 2."); } throw new IOException("State is not an expected array of length 2."); } } else { // PENDING - I18N if (log.isLoggable(Level.SEVERE)) { log.log(Level.SEVERE, "State is not an expected array of length 2."); } throw new IOException("State is not an expected array of length 2."); } } writeState(context, view); } /** *

* Take the argument state and write it into the output using the current {@link ResponseWriter}, which * must be correctly positioned already. *

* *

* If the {@link jakarta.faces.application.StateManager.SerializedView} is to be written out to hidden fields, the * implementation must take care to make all necessary character replacements to make the Strings suitable for inclusion * as an HTTP request paramater. *

* *

* If the state saving method for this application is * {@link jakarta.faces.application.StateManager#STATE_SAVING_METHOD_CLIENT}, the implementation may encrypt the state * to be saved to the client. We recommend that the state be unreadable by the client, and also be tamper evident. The * reference implementation follows these recommendations. *

* * @deprecated This method has been replaced by * {@link #writeState(jakarta.faces.context.FacesContext,java.lang.Object)}. The default implementation creates a two * element Object array with the first element being the return from calling * {@link SerializedView#getStructure}, and the second being the return from {@link SerializedView#getState}. It then * passes this Object array to {@link #writeState}. * * @param context The {@link FacesContext} instance for the current request * @param state The serialized state information previously saved * * @throws IOException if the state cannot be written for any reason * */ @Deprecated public void writeState(FacesContext context, SerializedView state) throws IOException { if (state != null) { writeState(context, new Object[] { state.getStructure(), state.getState() }); } } /** *

* If the preceding call to {@link #writeState(jakarta.faces.context.FacesContext, java.lang.Object)} was stateless, * return {@code true}. If the preceding call to {@code writeState()} was stateful, return {@code false}. Otherwise * throw {@code IllegalStateException}. *

* *
* *

* To preserve backward compatibility with custom implementations that may have extended from an earlier version of this * class, an implementation is provided that returns false. A compliant implementation must override this * method to take the specified action. *

* *
* * @param context The {@link FacesContext} instance for the current request * @param viewId View identifier of the view to be restored * @throws NullPointerException if the argument {@code context} is {@code null}. * @throws IllegalStateException if this method is invoked and the statefulness of the preceding call to * {@link #writeState(jakarta.faces.context.FacesContext, java.lang.Object)} cannot be determined. * * @since 2.2 * * * @return the value of the statelessness of this run through the lifecycle. * */ public boolean isStateless(FacesContext context, String viewId) { return false; } /** *

* The implementation must inspect the current request and return an Object * representing the tree structure and component state passed in to a previous invocation of * {@link #writeState(jakarta.faces.context.FacesContext,java.lang.Object)}. *

* *

* If the state saving method for this application is * {@link jakarta.faces.application.StateManager#STATE_SAVING_METHOD_CLIENT}, writeState() will have * encrypted the state in a tamper evident manner. If the state fails to decrypt, or decrypts but indicates evidence of * tampering, a {@link jakarta.faces.application.ProtectedViewException} must be thrown. *

* *

* For backwards compatability with existing ResponseStateManager implementations, the default * implementation of this method calls {@link #getTreeStructureToRestore} and {@link #getComponentStateToRestore} and * creates and returns a two element Object array with element zero containing the structure * property and element one containing the state property of the SerializedView. *

* * @since 1.2 * * @param context The {@link FacesContext} instance for the current request * @param viewId View identifier of the view to be restored * * @return the tree structure and component state Object passed in to writeState. If this is an initial * request, this method returns null. */ public Object getState(FacesContext context, String viewId) { Object stateArray[] = { getTreeStructureToRestore(context, viewId), getComponentStateToRestore(context) }; return stateArray; } /** *

* The implementation must inspect the current request and return the tree structure Object passed to it on a previous * invocation of writeState(). *

* * @deprecated This method has been replaced by {@link #getState}. The default implementation returns null. * * @param context The {@link FacesContext} instance for the current request * @param viewId View identifier of the view to be restored * * @return the tree structure portion of the state */ @Deprecated public Object getTreeStructureToRestore(FacesContext context, String viewId) { return null; } /** *

* The implementation must inspect the current request and return the component state Object passed to it on a previous * invocation of writeState(). *

* * @deprecated This method has been replaced by {@link #getState}. The default implementation returns null. * * @param context The {@link FacesContext} instance for the current request * * @return the component state portion of the state * */ @Deprecated public Object getComponentStateToRestore(FacesContext context) { return null; } /** *

* Return true if the current request is a postback. This method is leveraged from the Restore View Phase to * determine if {@link jakarta.faces.application.ViewHandler#restoreView} or * {@link jakarta.faces.application.ViewHandler#createView} should be called. The default implementation must return * true if this ResponseStateManager instance wrote out state on a previous request to which * this request is a postback, false otherwise. *

* *

* The implementation of this method for the Standard HTML RenderKit must consult the * {@link jakarta.faces.context.ExternalContext}'s requestParameterMap and return true if and * only if there is a key equal to the value of the symbolic constant {@link #VIEW_STATE_PARAM}. *

* *

* For backwards compatibility with implementations of ResponseStateManager prior to Jakarta Server Faces * 1.2, a default implementation is provided that consults the {@link jakarta.faces.context.ExternalContext}'s * requestParameterMap and return true if its size is greater than 0. *

* * @param context the {@code FacesContext} for the current request. * * @return the value as specified above * * @since 1.2 */ public boolean isPostback(FacesContext context) { return !context.getExternalContext().getRequestParameterMap().isEmpty(); } /** *

* Return the specified state as a String without any markup related to the rendering technology supported * by this ResponseStateManager. *

* * @param context the {@link FacesContext} for the current request * @param state the state from which the String version will be generated from * @return the view state for this request without any markup specifics * * @since 2.0 */ public String getViewState(FacesContext context, Object state) { return null; } /** *

* Compliant implementations must return a cryptographically strong token for use to protect views in this application. * For backwards compatability with earlier revisions, a default implementation is provided that simply returns * null. *

* * @param context the {@link FacesContext} for the current request * * @return a cryptographically strong value * * @since 2.2 */ public String getCryptographicallyStrongTokenFromSession(FacesContext context) { return null; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy