com.sun.faces.context.flash
public class ELFlash extends javax.faces.context.Flash
How this implementation works
This class is an application singleton. It has one ivar, innerMap. Entries are added to and removed from this map as needed according to how the flash scope is defined in the spec. This implementation never touches the session, nor does it cause the session to be created.
Most of the hairy logic is encapsulated with in the inner class PreviousNextFlashInfoManager. An instance of this class is obtained by calling one of the variants of getCurrentFlashManager(). When the instance is no longer needed for this request, call releaseCurrentFlashManager().
Two very important methods are getPhaseMapForWriting() and getPhaseMapForReading(). These methods are the basis for the Map implementation methods. Methods that need to write to the map use getPhaseMapForWriting(), those that need to read use getPhaseMapForReading(). These methods allow for the laziness that allows us to only incur a cost when the flash is actually written to.
The operation of this class is intimately tied to the request processing lifecycle. Let's break down every run thru the request processing lifecycle into two parts called "previous" and "next". We use the names "previous" and "next" to indicate the persistence and timing of the data that is stored in the flash. Consider two runs through the requset processing lifecle: N and N+1. On request N, there is no "previous" request. On Request N, any writes to the flash that happen during RENDER RESPONSE go to the "next" flash map. This means they are available for the ENTIRE run though the request processing lifecycle on request N+1. Any entries put into the "next" flash map on request N will be expired at the end of request N+1. Now, when we get into request N+1 what was considered "next" on request N, is now called "previous" from the perspective of request N+1. Any reads from the flash during request N+1 come from the "previous" map. Any writes to the flash before RENDER RESPONSE go to the "previous" map. Any writes to the flash during RENDER RESPNOSE go to the "next" map.
Modifier and Type | Class and Description |
---|---|
private static class |
ELFlash.CONSTANTS |
private static class |
ELFlash.FlashInfo
Encapsulate one of the two maps that back the flash for the
current request.
|
private static class |
ELFlash.LifetimeMarker |
private static class |
ELFlash.PreviousNextFlashInfoManager
On any given request, there are actually two maps behind the
flash.
|
Modifier and Type | Field and Description |
---|---|
(package private) static java.lang.String |
FLASH_ATTRIBUTE_NAME
This constant is used as the key in the application map that
stores the singleton ELFlash instance.
|
(package private) static java.lang.String |
FLASH_COOKIE_NAME
This constant is used as the name of the cookie sent to the
client.
|
(package private) static java.lang.String |
FLASH_NOW_REQUEST_KEY
This constant is used as the key the request map used, in the
FlashELResolver, to convey the name of the property being
accessed via 'now'.
|
private java.util.Map<java.lang.String,java.util.Map<java.lang.String,java.lang.Object>> |
flashInnerMap
Keys in this map are the string version of sequence numbers
obtained via calls to
getNewSequenceNumber() . |
private ByteArrayGuardAESCTR |
guard |
private static java.util.logging.Logger |
LOGGER |
private int |
numberOfConcurentFlashUsers |
private long |
numberOfFlashesBetweenFlashReapings |
(package private) static java.lang.String |
PREFIX
These constants are referenced from other source files in this
package.
|
private java.util.concurrent.atomic.AtomicLong |
sequenceNumber |
Modifier | Constructor and Description |
---|---|
private |
ELFlash()
Creates a new instance of ELFlash
|
Modifier and Type | Method and Description |
---|---|
void |
clear() |
(package private) void |
clearKeepFlag(javax.faces.context.FacesContext context) |
protected java.lang.Object |
clone() |
boolean |
containsKey(java.lang.Object key) |
boolean |
containsValue(java.lang.Object value) |
void |
doLastPhaseActions(javax.faces.context.FacesContext context,
boolean outgoingResponseIsRedirect)
This is the most magic of methods.
|
void |
doPostPhaseActions(javax.faces.context.FacesContext context) |
void |
doPrePhaseActions(javax.faces.context.FacesContext context) |
java.util.Set<java.util.Map.Entry<java.lang.String,java.lang.Object>> |
entrySet() |
java.lang.Object |
get(java.lang.Object key) |
private javax.servlet.http.Cookie |
getCookie(javax.faces.context.ExternalContext extContext)
Return the cookie that came from the browser, if any.
|
private ELFlash.PreviousNextFlashInfoManager |
getCurrentFlashManager(javax.faces.context.FacesContext context,
java.util.Map<java.lang.Object,java.lang.Object> contextMap,
javax.servlet.http.Cookie cookie)
Called on the preRestoreView phase if the browser sent us a
cookie.
|
private ELFlash.PreviousNextFlashInfoManager |
getCurrentFlashManager(java.util.Map<java.lang.Object,java.lang.Object> contextMap,
boolean create)
Called when you need to get access to the flashManager.
|
static java.util.Map<java.lang.String,java.lang.Object> |
getFlash()
Returns the flash
Map for this application. |
static ELFlash |
getFlash(javax.faces.context.ExternalContext extContext,
boolean create) |
private static java.lang.String |
getLogPrefix(javax.faces.context.FacesContext context) |
private long |
getNewSequenceNumber() |
private java.util.Map<java.lang.String,java.lang.Object> |
getPhaseMapForReading()
Always return the map for the "previous" request.
|
private java.util.Map<java.lang.String,java.lang.Object> |
getPhaseMapForWriting()
If the current phase is earlier than RENDER_RESPONSE, return
the map for the "previous" request.
|
boolean |
isEmpty() |
(package private) boolean |
isKeepFlagSet(javax.faces.context.FacesContext context) |
boolean |
isKeepMessages() |
boolean |
isRedirect() |
void |
keep(java.lang.String key) |
java.util.Set<java.lang.String> |
keySet() |
private java.util.Map<java.lang.String,java.lang.Object> |
loggingGetPhaseMapForReading(boolean loggingEnabled) |
private java.util.Map<java.lang.String,java.lang.Object> |
loggingGetPhaseMapForWriting(boolean loggingEnabled) |
private void |
maybeWriteCookie(javax.faces.context.FacesContext context,
ELFlash.PreviousNextFlashInfoManager flashManager) |
java.lang.Object |
put(java.lang.String key,
java.lang.Object value) |
void |
putAll(java.util.Map<? extends java.lang.String,?> t) |
void |
putNow(java.lang.String key,
java.lang.Object value) |
private void |
reapFlashes() |
private void |
releaseCurrentFlashManager(java.util.Map<java.lang.Object,java.lang.Object> contextMap) |
java.lang.Object |
remove(java.lang.Object key) |
private boolean |
responseCompleteWasJustSetTrue(javax.faces.context.FacesContext context,
java.util.Map<java.lang.Object,java.lang.Object> contextMap) |
(package private) void |
restoreAllMessages(javax.faces.context.FacesContext context) |
(package private) void |
saveAllMessages(javax.faces.context.FacesContext context) |
private void |
setCookie(javax.faces.context.FacesContext context,
ELFlash.PreviousNextFlashInfoManager flashManager,
javax.servlet.http.Cookie toSet)
Set the cookie iff the response was not yet committed.
|
(package private) void |
setKeepFlag(javax.faces.context.FacesContext context) |
void |
setKeepMessages(boolean newValue) |
void |
setRedirect(boolean newValue) |
int |
size() |
java.util.Collection<java.lang.Object> |
values() |
private java.util.Map<java.lang.String,java.util.Map<java.lang.String,java.lang.Object>> flashInnerMap
Keys in this map are the string version of sequence numbers
obtained via calls to getNewSequenceNumber()
. Values are
the actual Map instances that back the actual Map methods on this
class. All writes to and reads from this map are done by the
ELFlash.PreviousNextFlashInfoManager
inner class.
private final java.util.concurrent.atomic.AtomicLong sequenceNumber
private int numberOfConcurentFlashUsers
private long numberOfFlashesBetweenFlashReapings
private ByteArrayGuardAESCTR guard
private static final java.util.logging.Logger LOGGER
static final java.lang.String PREFIX
These constants are referenced from other source files in this package. This one is a disambiguator prefix.
static final java.lang.String FLASH_ATTRIBUTE_NAME
This constant is used as the key in the application map that stores the singleton ELFlash instance.
static final java.lang.String FLASH_COOKIE_NAME
This constant is used as the name of the cookie sent to the client.
static final java.lang.String FLASH_NOW_REQUEST_KEY
This constant is used as the key the request map used, in the FlashELResolver, to convey the name of the property being accessed via 'now'.
public static java.util.Map<java.lang.String,java.lang.Object> getFlash()
Returns the flash Map
for this application. This is
a convenience method that calls
FacesContext.getCurrentInstance()
and then calls the
overloaded getFlash()
that takes a
FacesContext
with it.
Map
for this session.public static ELFlash getFlash(javax.faces.context.ExternalContext extContext, boolean create)
extContext
- the ExternalContext
for this request.create
- true
to create a new instance for this request if
necessary; false
to return null
if there's no
instance in the current session
.Map
for this session.public boolean isKeepMessages()
isKeepMessages
in class javax.faces.context.Flash
public void setKeepMessages(boolean newValue)
setKeepMessages
in class javax.faces.context.Flash
public boolean isRedirect()
isRedirect
in class javax.faces.context.Flash
public void setRedirect(boolean newValue)
setRedirect
in class javax.faces.context.Flash
public java.lang.Object get(java.lang.Object key)
public java.lang.Object put(java.lang.String key, java.lang.Object value)
public java.lang.Object remove(java.lang.Object key)
public boolean containsKey(java.lang.Object key)
public boolean containsValue(java.lang.Object value)
public void putAll(java.util.Map<? extends java.lang.String,?> t)
public java.util.Collection<java.lang.Object> values()
public int size()
public void clear()
protected java.lang.Object clone() throws java.lang.CloneNotSupportedException
clone
in class java.lang.Object
java.lang.CloneNotSupportedException
public java.util.Set<java.util.Map.Entry<java.lang.String,java.lang.Object>> entrySet()
public boolean isEmpty()
public java.util.Set<java.lang.String> keySet()
public void keep(java.lang.String key)
keep
in class javax.faces.context.Flash
public void putNow(java.lang.String key, java.lang.Object value)
putNow
in class javax.faces.context.Flash
public void doPrePhaseActions(javax.faces.context.FacesContext context)
doPrePhaseActions
in class javax.faces.context.Flash
public void doPostPhaseActions(javax.faces.context.FacesContext context)
doPostPhaseActions
in class javax.faces.context.Flash
public void doLastPhaseActions(javax.faces.context.FacesContext context, boolean outgoingResponseIsRedirect)
This is the most magic of methods. There are several scenarios
in which this method can be called, but the first time it is
called for a request it takes action, while on subsequent times
it returns without taking action. This is due to the call to
releaseCurrentFlashManager(java.util.Map
. After this call, any calls
to getCurrentFlashManager(java.util.Map
will return null.
Scenario 1: normal request ending. This will be called after the RENDER_RESPONSE phase executes. outgoingResponseIsRedirect will be false.
Scenario 2: navigationHandler asks extContext for redirect. In this case, extContext calls this method directly, outgoingResponseIsRedirect will be true.
Scenario 3: extContext.flushBuffer(): As far as I can tell, this is only called in the JSP case, but it's good to call it from there anyway, because we need to write our cookie before the response is committed. outgoingResponseIsRedirect is false.
Scenario 4: after rendering the response in JSP, but before the buffer is flushed. In the JSP case, I've found this necessary because the call to extContext.flushBuffer() is too late, the response has already been committed by that point. outgoingResponseIsRedirect is false.
private void maybeWriteCookie(javax.faces.context.FacesContext context, ELFlash.PreviousNextFlashInfoManager flashManager)
void setKeepFlag(javax.faces.context.FacesContext context)
void clearKeepFlag(javax.faces.context.FacesContext context)
boolean isKeepFlagSet(javax.faces.context.FacesContext context)
private long getNewSequenceNumber()
private void reapFlashes()
private boolean responseCompleteWasJustSetTrue(javax.faces.context.FacesContext context, java.util.Map<java.lang.Object,java.lang.Object> contextMap)
private static java.lang.String getLogPrefix(javax.faces.context.FacesContext context)
private java.util.Map<java.lang.String,java.lang.Object> loggingGetPhaseMapForWriting(boolean loggingEnabled)
private java.util.Map<java.lang.String,java.lang.Object> getPhaseMapForWriting()
If the current phase is earlier than RENDER_RESPONSE, return the map for the "previous" request. Otherwise, return the map for the "next" request. Note that we use getCurrentFlashManager(contextMap,true). This is because if this method is being called, we know we actually need the map, so we have to ensure the underlying data structure is present before trying to access it.
private java.util.Map<java.lang.String,java.lang.Object> loggingGetPhaseMapForReading(boolean loggingEnabled)
private java.util.Map<java.lang.String,java.lang.Object> getPhaseMapForReading()
Always return the map for the "previous" request. Note that we use getCurrentFlashManager(contextMap,false). This is because if this method is being called, and there is pre-existing data in the flash from a previous write, then the PreviousNextFlashInfoManager will already have been created. If there is not pre-existing data, we don't create the PreviousNextFlashInfoManager, and therefore just return the empty map.
void saveAllMessages(javax.faces.context.FacesContext context)
void restoreAllMessages(javax.faces.context.FacesContext context)
private javax.servlet.http.Cookie getCookie(javax.faces.context.ExternalContext extContext)
Return the cookie that came from the browser, if any.
private void setCookie(javax.faces.context.FacesContext context, ELFlash.PreviousNextFlashInfoManager flashManager, javax.servlet.http.Cookie toSet)
Set the cookie iff the response was not yet committed. If the response was committed, log a warning.
private void releaseCurrentFlashManager(java.util.Map<java.lang.Object,java.lang.Object> contextMap)
private ELFlash.PreviousNextFlashInfoManager getCurrentFlashManager(java.util.Map<java.lang.Object,java.lang.Object> contextMap, boolean create)
Called when you need to get access to the flashManager. If argument create is true, and no instance of the FlashManager exists for this request, create it and store it in the contextMap.
private ELFlash.PreviousNextFlashInfoManager getCurrentFlashManager(javax.faces.context.FacesContext context, java.util.Map<java.lang.Object,java.lang.Object> contextMap, javax.servlet.http.Cookie cookie)
Called on the preRestoreView phase if the browser sent us a cookie. If no instance of the FlashManager exists for this request, create it and store it in the contextMap.
Copyright © 2002-2010 Oracle America, Inc. All Rights Reserved.