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

com.sun.faces.context.flash.FlashELResolver Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2023 Contributors to Eclipse Foundation.
 * 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 com.sun.faces.context.flash;

import jakarta.el.ELContext;
import jakarta.el.ELResolver;
import jakarta.el.PropertyNotFoundException;
import jakarta.el.PropertyNotWritableException;
import jakarta.faces.FactoryFinder;
import jakarta.faces.context.ExternalContext;
import jakarta.faces.context.FacesContext;
import jakarta.faces.context.Flash;
import jakarta.faces.context.FlashFactory;
import java.util.Map;

/**
 * 

* Provide a feature semantically identical to the * "flash" concept in Ruby on * Rails. *

* *

* The feature is exposed to users via a custom ELResolver which introduces a new implicit object, * flash. The flash functions as Map and can be used in getValue( ) or * setValue( * ) expressions. *

* *

* Usage *

* *

* Consider three Faces views: viewA, viewB, and viewC. The user first views viewA, then clicks a button and is shown * viewB, where she clicks a button and is shown viewC. If values are stored into the flash during the rendering or * postback phases of viewA, they are available to during the rendering phase of viewB, but are not available during the * rendering or postback phases of viewC. In other words, values stored into the flash on "this" request are accessible * for the "next" request, but not thereafter. *

* *

* There are three ways to access the flash. *

* *
    *
  1. * Using an Expression Language Expression, such as using #{flash.foo} as the value of an attribute in a page. *
  2. *
  3. * Using the EL API, such as: * *

    * * FacesContext context = FacesContext.getCurrentInstance(); * ValueExpression flashExpression = context.getApplication(). * createValueExpression(context.getELContext(), "#{flash.foo}", * null, Object.class); * flashExpression.setValue(context.getELContext(), "Foo's new value"); * *

    * *
  4. *
  5. *

    * Using getting the {@link ELFlash} directly, such as: *

    * *

    * * Map<String,Object> flash = ELFlash.getFlash(); * flash.put("foo", "Foo's new value"); * *

    *
  6. *
* *

* The main entry point to this feature is the first one. This library includes a simple custom tag, jsfExt:set, that evaluates an expression and sets its value into * another expression. jsfExt:set can be used to store values into the flash from JSP pages, like this: *

* *

* <jsfExt:set var="#{flash.foo}" value="fooValue" * /> *

* *

* or this: *

* *

* <jsfExt:set var="#{flash.keep.bar}" value="#{user.name}" * /> *

* *

* or even this: *

* *

* * <jsfExt:set var="#{flash.now.baz}" value="#{cookie.userCookie}" /> * * <h:outputText value="#{flash.now.baz}" /> * * *

* *

* Related Classes *

* *

* The complete list of classes that make up this feature is *

* *
    *
  • FlashELResolver
  • *
  • {@link ELFlash}
  • *
*/ public class FlashELResolver extends ELResolver { /** *

* Not intended for manual invocation. Only called by the Faces Runtime. *

*/ public FlashELResolver() { } // ------------------------------------------------------ Manifest Constants private static final String FLASH_VARIABLE_NAME = "flash"; private static final String FLASH_NOW_VARIABLE_NAME = "now"; private static final String FLASH_KEEP_VARIABLE_NAME = "keep"; // ------------------------------------------------ VariableResolver Methods /** *

* Hook into the EL resolution process to introduce the flash implicit object. If property is * null, take no action and return null. if base is null, return null. If * base is an instance of ELFlash and property is the literal string "keep", set a ThreadLocal * property that will be inspected by the flash on the next link in the resolution chain and return the * ELFlash instance. If base is an instance of ELFlash and property * is the literal string "now", return the result of calling getRequestMap( ) on the * ExternalContext for the FacesContext for this request. Call * setPropertyResolved(true) on the ELContext where appropriate. *

* * @throws PropertyNotFoundException if property is null. */ @Override public Object getValue(ELContext elContext, Object base, Object property) { if (null == property) { // take no action. return null; } Object result = null; if (null == base) { return null; } // If the base argument is the flash itself... else if (base instanceof Flash) { FacesContext facesContext = (FacesContext) elContext.getContext(FacesContext.class); ExternalContext extCtx = facesContext.getExternalContext(); // and the property argument is "keep"... switch (property.toString()) { // Otherwise, if base is the flash, and property is "now"... case FLASH_KEEP_VARIABLE_NAME: elContext.setPropertyResolved(true); // then this is a request to promote the value // "property", which is assumed to have been previously // stored in request scope via the "flash.now" // expression, to flash scope. result = base; // Set a flag so the flash itself can look in the request // and promote the value to the next request FlashFactory ff = (FlashFactory) FactoryFinder.getFactory(FactoryFinder.FLASH_FACTORY); ff.getFlash(true); ELFlash.setKeepFlag(facesContext); break; case FLASH_NOW_VARIABLE_NAME: // PENDING(edburns): use FacesContext.getAttributes() instead of // request scope. Map requestMap = extCtx.getRequestMap(); requestMap.put(ELFlash.FLASH_NOW_REQUEST_KEY, property); elContext.setPropertyResolved(true); result = requestMap; break; default: result = null; break; } } return result; } /** *

* Return the valid Class for a future set operation, which will always be null because sets * happen via the MapELResolver operating on the {@link ELFlash} instance as a Map. *

* * @throws PropertyNotFoundException if property is null. */ @Override public Class getType(ELContext elContext, Object base, Object property) { if (null != base) { return null; } if (null == property) { String message = " base " + base + " property " + property; throw new PropertyNotFoundException(message); } if (property.toString().equals(FLASH_VARIABLE_NAME)) { elContext.setPropertyResolved(true); } return null; } /** *

* This method will throw PropertyNotWritableException if called with a null base * and a property value equal to the literal string "flash". This is because set operations normally go * through the MapELResolver via the ELFlash Map. *

* *

* In other words, do not call this method directly to set a value into the flash! The only way to access the flash is * via the EL API. *

* * @throws PropertyNotFoundException if base is null and property is * null. * @throws PropertyNotWritableException if base is null and property is the * literal string "flash". */ @Override public void setValue(ELContext elContext, Object base, Object property, Object value) { if (base != null) { return; } if (property == null) { String message = " base " + base + " property " + property; throw new PropertyNotFoundException(message); } if (property.toString().equals(FLASH_VARIABLE_NAME)) { elContext.setPropertyResolved(true); throw new PropertyNotWritableException(property.toString()); } } /** *

* Returns true because write operations take place via the MapELResolver on the actual * {@link ELFlash} instance. *

* * @throws PropertyNotFoundException if base is null and property is * null. */ @Override public boolean isReadOnly(ELContext elContext, Object base, Object property) { if (base != null) { return false; } if (property == null) { String message = " base " + base + " property " + property; throw new PropertyNotFoundException(message); } if (property.toString().equals(FLASH_VARIABLE_NAME)) { elContext.setPropertyResolved(true); return true; } return false; } /** *

* If base is non-null and is the literal string "flash", return Object.class. *

*/ @Override public Class getCommonPropertyType(ELContext context, Object base) { Class result = null; if (null != base) { if (FLASH_VARIABLE_NAME.equals(base.toString())) { result = Object.class; } } return result; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy