private Object _saveStateToCache(FacesContext context, Object viewState, UIViewRoot root)
{
ExternalContext extContext = context.getExternalContext();
RequestContext trinContext = RequestContext.getCurrentInstance();
TokenCache cache = _getViewCache(trinContext, extContext);
assert(cache != null);
// get per window view cache key with "." separator suffix to separate the SubKeyMap keys
String subkey = _getViewCacheKey(extContext, trinContext, _SUBKEY_SEPARATOR);
Map<String, Object> sessionMap = extContext.getSessionMap();
Map<String, PageState> stateMap = new SubKeyMap<PageState>(sessionMap, subkey);
// Sadly, we can't save just a SerializedView, because we should
// save a serialized object, and SerializedView is a *non*-static
// inner class of StateManager
PageState pageState = new PageState(
context,
viewState,
// Save the view root into the page state as a transient
// if this feature has not been disabled
_useViewRootCache(context) ? root : null);
String requestToken = _getRequestTokenForResponse(context);
String token;
// If we have a cached token that we want to reuse,
// and that token hasn't disappeared from the cache already
// (unlikely, but not impossible), use the stateMap directly
// without asking the cache for a new token
if ((requestToken != null) && cache.isAvailable(requestToken))
{
// NOTE: under *really* high pressure, the cache might
// have been emptied between the isAvailable() call and
// this put(). This seems sufficiently implausible to
// be worth punting on
stateMap.put(requestToken, pageState);
token = requestToken;
// NOTE 2: we have not pinned this reused state to any old state
// This is OK for current uses of pinning and state reuse,
// as pinning stays constant within a window, and we're not
// erasing pinning at all.
}
else
{
// See if we should pin this new state to any old state
String pinnedToken = (String)extContext.getRequestMap().get(_PINNED_STATE_TOKEN_KEY);
token = cache.addNewEntry(pageState,
stateMap,
pinnedToken);
}