Return-Path: X-Original-To: apmail-myfaces-dev-archive@www.apache.org Delivered-To: apmail-myfaces-dev-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id A98CFD77D for ; Wed, 14 Nov 2012 22:50:47 +0000 (UTC) Received: (qmail 80412 invoked by uid 500); 14 Nov 2012 22:50:47 -0000 Delivered-To: apmail-myfaces-dev-archive@myfaces.apache.org Received: (qmail 80369 invoked by uid 500); 14 Nov 2012 22:50:47 -0000 Mailing-List: contact dev-help@myfaces.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: "MyFaces Development" Delivered-To: mailing list dev@myfaces.apache.org Received: (qmail 80359 invoked by uid 99); 14 Nov 2012 22:50:47 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 14 Nov 2012 22:50:47 +0000 X-ASF-Spam-Status: No, hits=-0.5 required=5.0 tests=FREEMAIL_ENVFROM_END_DIGIT,RCVD_IN_DNSWL_LOW,SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (nike.apache.org: domain of lu4242@gmail.com designates 209.85.210.53 as permitted sender) Received: from [209.85.210.53] (HELO mail-da0-f53.google.com) (209.85.210.53) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 14 Nov 2012 22:50:39 +0000 Received: by mail-da0-f53.google.com with SMTP id g9so378464dad.12 for ; Wed, 14 Nov 2012 14:50:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :content-type; bh=qXEeJkrMi2+H9WhcTm+K+pOnsu67VeoEz+YanKr0YpM=; b=UGnoearNv/qa0vLBJn5gHTzDGOUSiSFnsJEvraZC/hLZV8bt3PwLNwQ+4TI+H9BO2V J0WWqPdH2xSK9d49c0+lJ/HCBLEBr6sdUtEyqOiAqijlB4sRSdLvvIHI9BCu1kCs1kx1 fVhwXp3fNrpYzcUFMPry48CGLAfyZUQJlUsroBU3qKVK/UPOLUIramvUa7BRtu5ZJ8+E gjuxWCNKSv3mARznkbeiCFtuHsfkhIOm8aBf6KJ7tOKfh212LPvTT+7OmkereEjp35ti SPZrcpCjiy96c+hzqrCtmhn3L0U46ysAC+qNTj0oR7iIOd1PZHckVLFNCwHtb/Uh6oi6 yeSg== MIME-Version: 1.0 Received: by 10.68.239.9 with SMTP id vo9mr83397053pbc.83.1352933417937; Wed, 14 Nov 2012 14:50:17 -0800 (PST) Received: by 10.66.119.201 with HTTP; Wed, 14 Nov 2012 14:50:17 -0800 (PST) In-Reply-To: <1352932986.72528.YahooMailNeo@web28905.mail.ir2.yahoo.com> References: <20121114212336.19C7723889D7@eris.apache.org> <1352931493.13234.YahooMailNeo@web28904.mail.ir2.yahoo.com> <1352932986.72528.YahooMailNeo@web28905.mail.ir2.yahoo.com> Date: Wed, 14 Nov 2012 17:50:17 -0500 Message-ID: Subject: Re: svn commit: r1409414 - in /myfaces/core/trunk/impl: ./ src/main/java/org/apache/myfaces/renderkit/ From: Leonardo Uribe To: MyFaces Development , Mark Struberg Content-Type: text/plain; charset=ISO-8859-1 X-Virus-Checked: Checked by ClamAV on apache.org 2012/11/14 Mark Struberg : > > > > > Leo we HAD that already in production (with an IBM JVM). Does that count? > > using the hashCode to speed up caches is perfectly fine. But only for _excluding_ matches, Getting the same hashCode doesn't make sure something is unique. > > Also in the private mail you pointed to an example yourself [1]: > > > [1] pry(main)> "a".hash > => 100 [2] pry(main)> "\0a".hash > => 100 [3] pry(main)> "\0\0a".hash > => 100 [4] pry(main)> "\0\0\0a".hash > => 100 [5] pry(main)> "\0\0\0\0a".hash > => 100 [6] pry(main)> "\0\0\0\0\0a".hash > => 100 > but you cannot put a \0 in a file name, because it is an invalid character for a file name, right? We are looking for REAL file names that can result in a viewId. For example: /home.xhtml /module/page.xhtml and so on. In practice, the probability of have two REAL pages that derives a viewId and that the hashCode could be the same is astronomical. > It's just not guaranteed. > > LieGrue, > strub > > > > [1] http://martin.kleppmann.com/2012/06/18/java-hashcode-unsafe-for-distributed-systems.html > > > > ----- Original Message ----- >> From: Leonardo Uribe >> To: MyFaces Development ; Mark Struberg >> Cc: >> Sent: Wednesday, November 14, 2012 11:34 PM >> Subject: Re: svn commit: r1409414 - in /myfaces/core/trunk/impl: ./ src/main/java/org/apache/myfaces/renderkit/ >> >> 2012/11/14 Leonardo Uribe : >>> Hi >>> >>> 2012/11/14 Mark Struberg : >>>> Leo, there was a reason I removed it. >>>> >>>> >>>> Even after discussing this over 10 mails in a private thread you >> don't get it it seems. I will open a VOTE about principal design >> fundamentals and we will act according to this. >>>> >>>> Just you be prepated: A HASH IS NOT UNIQUE! >>>> >>> >>> But I have told you multiple times, the algorithm does not rely on the >>> hash to be unique, relies on the counter. >>> >>>> Also saying in the mails you understand and then doing the same crazy >> code again is just plain ****** >>>> >>>> I gonna revert it now and will write up the VOTE >>> >>> The best way to resolve this is putting the arguments on the table and >>> vote over that, right? after the vote we can do the necessary changes >>> over the code. I have committed the fix that I suppose is correct. >>> >> >> It is more, could you please try if the fix proposed by me works in your case? >> could you please show two viewIds that can be written as valid file names that >> has the same hashCode? I'm open to change my mind, but first I need >> concrete arguments to do that. >> >>> regards, >>> >>> Leonardo >>> >>>> >>>> LieGrue, >>>> strub >>>> >>>> >>>> >>>> >>>> ----- Original Message ----- >>>>> From: "lu4242@apache.org" >>>>> To: commits@myfaces.apache.org >>>>> Cc: >>>>> Sent: Wednesday, November 14, 2012 10:23 PM >>>>> Subject: svn commit: r1409414 - in /myfaces/core/trunk/impl: ./ >> src/main/java/org/apache/myfaces/renderkit/ >>>>> >>>>> Author: lu4242 >>>>> Date: Wed Nov 14 21:23:35 2012 >>>>> New Revision: 1409414 >>>>> >>>>> URL: http://svn.apache.org/viewvc?rev=1409414&view=rev >>>>> Log: >>>>> MYFACES-3638 revert commit 1408993 to include later solution >> without >>>>> refactoring. >>>>> >>>>> Added: >>>>> >>>>> >> myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/renderkit/SessionIdGenerator.java >>>>> - copied unchanged from r1408992, >>>>> >> myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/renderkit/SessionIdGenerator.java >>>>> Removed: >>>>> >>>>> >> myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/renderkit/CounterKeyFactory.java >>>>> >>>>> >> myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/renderkit/KeyFactory.java >>>>> >>>>> >> myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/renderkit/RandomKeyFactory.java >>>>> >>>>> >> myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/renderkit/SecureRandomKeyFactory.java >>>>> >>>>> >> myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/renderkit/SerializedViewKey.java >>>>> >>>>> >> myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/renderkit/SessionViewStorageFactory.java >>>>> Modified: >>>>> myfaces/core/trunk/impl/ (props changed) >>>>> >>>>> >> myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/renderkit/ServerSideStateCacheImpl.java >>>>> >>>>> Propchange: myfaces/core/trunk/impl/ >>>>> >> ------------------------------------------------------------------------------ >>>>> --- svn:ignore (original) >>>>> +++ svn:ignore Wed Nov 14 21:23:35 2012 >>>>> @@ -7,7 +7,8 @@ target >>>>> *.iml >>>>> *.ipr >>>>> *.iws >>>>> -.idea >>>>> .settings >>>>> + >>>>> cobertura.ser >>>>> + >>>>> test-output >>>>> >>>>> Modified: >>>>> >> myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/renderkit/ServerSideStateCacheImpl.java >>>>> URL: >>>>> >> http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/renderkit/ServerSideStateCacheImpl.java?rev=1409414&r1=1409413&r2=1409414&view=diff >>>>> >> ============================================================================== >>>>> --- >>>>> >> myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/renderkit/ServerSideStateCacheImpl.java >>>>> (original) >>>>> +++ >>>>> >> myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/renderkit/ServerSideStateCacheImpl.java >>>>> Wed Nov 14 21:23:35 2012 >>>>> @@ -30,16 +30,21 @@ import java.security.AccessController; >>>>> import java.security.PrivilegedActionException; >>>>> import java.security.PrivilegedExceptionAction; >>>>> import java.util.ArrayList; >>>>> +import java.util.Arrays; >>>>> import java.util.HashMap; >>>>> import java.util.List; >>>>> import java.util.Map; >>>>> +import java.util.Random; >>>>> import java.util.logging.Level; >>>>> import java.util.logging.Logger; >>>>> import java.util.zip.GZIPInputStream; >>>>> import java.util.zip.GZIPOutputStream; >>>>> +import javax.faces.application.ProjectStage; >>>>> >>>>> import javax.faces.context.ExternalContext; >>>>> import javax.faces.context.FacesContext; >>>>> +import org.apache.commons.codec.DecoderException; >>>>> +import org.apache.commons.codec.binary.Hex; >>>>> >>>>> import org.apache.commons.collections.map.AbstractReferenceMap; >>>>> import org.apache.commons.collections.map.ReferenceMap; >>>>> @@ -52,22 +57,22 @@ import org.apache.myfaces.shared.util.We >>>>> class ServerSideStateCacheImpl extends StateCache> Object> >>>>> { >>>>> private static final Logger log = >>>>> Logger.getLogger(ServerSideStateCacheImpl.class.getName()); >>>>> - >>>>> - private static final String SERIALIZED_VIEW_SESSION_ATTR= >>>>> + >>>>> + private static final String SERIALIZED_VIEW_SESSION_ATTR= >>>>> ServerSideStateCacheImpl.class.getName() + >>>>> ".SERIALIZED_VIEW"; >>>>> - >>>>> - private static final String >> RESTORED_SERIALIZED_VIEW_REQUEST_ATTR = >>>>> + >>>>> + private static final String >> RESTORED_SERIALIZED_VIEW_REQUEST_ATTR = >>>>> ServerSideStateCacheImpl.class.getName() + >>>>> ".RESTORED_SERIALIZED_VIEW"; >>>>> >>>>> - private static final String RESTORED_VIEW_KEY_REQUEST_ATTR = >>>>> + private static final String RESTORED_VIEW_KEY_REQUEST_ATTR = >>>>> ServerSideStateCacheImpl.class.getName() + >>>>> ".RESTORED_VIEW_KEY"; >>>>> - >>>>> + >>>>> /** >>>>> * Defines the amount (default = 20) of the latest views are >> stored in >>>>> session. >>>>> - * >>>>> + * >>>>> *

Only applicable if state saving method is >> "server" (= >>>>> default). >>>>> *

>>>>> - * >>>>> + * >>>>> */ >>>>> >> @JSFWebConfigParam(defaultValue="20",since="1.1", >>>>> classType="java.lang.Integer", group="state", >>>>> tags="performance") >>>>> private static final String NUMBER_OF_VIEWS_IN_SESSION_PARAM = >>>>> "org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION"; >>>>> @@ -75,8 +80,8 @@ class ServerSideStateCacheImpl extends S >>>>> /** >>>>> * Indicates the amount of views (default is not active) that >> should be >>>>> stored in session between sequential >>>>> * POST or POST-REDIRECT-GET if >>>>> org.apache.myfaces.USE_FLASH_SCOPE_PURGE_VIEWS_IN_SESSION is true. >>>>> - * >>>>> - *

Only applicable if state saving method is >> "server" (= >>>>> default). For example, if this param has value = 2 and >>>>> + * >>>>> + *

Only applicable if state saving method is >> "server" (= >>>>> default). For example, if this param has value = 2 and >>>>> * in your custom webapp there is a form that is clicked 3 >> times, only 2 >>>>> views >>>>> * will be stored and the third one (the one stored the first >> time) will be >>>>> * removed from session, even if the view can >>>>> @@ -88,14 +93,14 @@ class ServerSideStateCacheImpl extends S >>>>> @JSFWebConfigParam(since="2.0.6", >>>>> classType="java.lang.Integer", group="state", >>>>> tags="performance") >>>>> private static final String >> NUMBER_OF_SEQUENTIAL_VIEWS_IN_SESSION_PARAM >>>>> = >>>>> >> "org.apache.myfaces.NUMBER_OF_SEQUENTIAL_VIEWS_IN_SESSION"; >>>>> - >>>>> + >>>>> /** >>>>> * Default value for >>>>> >> org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION context >>>>> parameter. >>>>> */ >>>>> private static final int DEFAULT_NUMBER_OF_VIEWS_IN_SESSION = >> 20; >>>>> >>>>> /** >>>>> - * Indicate if the state should be serialized before save it >> on the >>>>> session. >>>>> + * Indicate if the state should be serialized before save it >> on the >>>>> session. >>>>> *

>>>>> * Only applicable if state saving method is >> "server" (= >>>>> default). >>>>> * If true (default) the state will >> be serialized >>>>> to a byte stream before it is written to the session. >>>>> @@ -107,7 +112,7 @@ class ServerSideStateCacheImpl extends S >>>>> >>>>> /** >>>>> * Indicates that the serialized state will be compressed >> before it is >>>>> written to the session. By default true. >>>>> - * >>>>> + * >>>>> * Only applicable if state saving method is >> "server" (= default) >>>>> and if >>>>> * >> org.apache.myfaces.SERIALIZE_STATE_IN_SESSION >>>>> is true (= default). >>>>> * If true (default) the serialized >> state will be >>>>> compressed before it is written to the session. >>>>> @@ -140,38 +145,38 @@ class ServerSideStateCacheImpl extends S >>>>> *

>>>>> * By default no cache is used, so views removed from session >> became >>>>> phantom references. >>>>> *

>>>>> - *
    >>>>> - *
  • off, no: default, no cache is used
  • >>>>> + *
      >>>>> + *
    • off, no: default, no cache is used
    • >>>>> *
    • hard-soft: use an >> ReferenceMap(AbstractReferenceMap.HARD, >>>>> AbstractReferenceMap.SOFT)
    • >>>>> *
    • soft: use an >> ReferenceMap(AbstractReferenceMap.SOFT, >>>>> AbstractReferenceMap.SOFT, true)
    • >>>>> *
    • soft-weak: use an >> ReferenceMap(AbstractReferenceMap.SOFT, >>>>> AbstractReferenceMap.WEAK, true)
    • >>>>> *
    • weak: use an >> ReferenceMap(AbstractReferenceMap.WEAK, >>>>> AbstractReferenceMap.WEAK, true)
    • >>>>> *
    >>>>> - * >>>>> + * >>>>> */ >>>>> @JSFWebConfigParam(defaultValue="off", >> expectedValues="off, >>>>> no, hard-soft, soft, soft-weak, weak", >>>>> since="1.2.5", >> group="state", >>>>> tags="performance") >>>>> private static final String CACHE_OLD_VIEWS_IN_SESSION_MODE = >>>>> "org.apache.myfaces.CACHE_OLD_VIEWS_IN_SESSION_MODE"; >>>>> - >>>>> + >>>>> /** >>>>> - * This option uses an hard-soft ReferenceMap, but it could >> cause a >>>>> + * This option uses an hard-soft ReferenceMap, but it could >> cause a >>>>> * memory leak, because the keys are not removed by any method >>>>> * (MYFACES-1660). So use with caution. >>>>> */ >>>>> private static final String >> CACHE_OLD_VIEWS_IN_SESSION_MODE_HARD_SOFT = >>>>> "hard-soft"; >>>>> - >>>>> + >>>>> private static final String >> CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT = >>>>> "soft"; >>>>> - >>>>> + >>>>> private static final String >> CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT_WEAK = >>>>> "soft-weak"; >>>>> - >>>>> + >>>>> private static final String >> CACHE_OLD_VIEWS_IN_SESSION_MODE_WEAK = >>>>> "weak"; >>>>> - >>>>> + >>>>> private static final String >> CACHE_OLD_VIEWS_IN_SESSION_MODE_OFF = >>>>> "off"; >>>>> >>>>> /** >>>>> * Allow use flash scope to keep track of the views used in >> session and the >>>>> previous ones, >>>>> * so server side state saving can delete old views even if >>>>> POST-REDIRECT-GET pattern is used. >>>>> - * >>>>> + * >>>>> *

    >>>>> * Only applicable if state saving method is >> "server" (= >>>>> default). >>>>> * The default value is false.

    >>>>> @@ -183,84 +188,90 @@ class ServerSideStateCacheImpl extends S >>>>> private static final String >> RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_NONE = >>>>> "none"; >>>>> private static final String >>>>> RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_SECURE_RANDOM = >> "secureRandom"; >>>>> private static final String >> RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_RANDOM = >>>>> "random"; >>>>> - >>>>> + >>>>> /** >>>>> * Adds a random key to the generated view state session >> token. >>>>> */ >>>>> - @JSFWebConfigParam(since="2.1.9, 2.0.15", >>>>> expectedValues="secureRandom, random, none", >>>>> + @JSFWebConfigParam(since="2.1.9, 2.0.15", >>>>> expectedValues="secureRandom, random, none", >>>>> defaultValue="none", >> group="state") >>>>> private static final String >> RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_PARAM >>>>> = >>>>> >> "org.apache.myfaces.RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN"; >>>>> - private static final String >>>>> RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_PARAM_DEFAULT = >>>>> + private static final String >>>>> RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_PARAM_DEFAULT = >>>>> RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_NONE; >>>>> >>>>> /** >>>>> * Set the default length of the random key added to the view >> state session >>>>> token. >>>>> - * By default is 8. >>>>> + * By default is 8. >>>>> */ >>>>> @JSFWebConfigParam(since="2.1.9, 2.0.15", >>>>> defaultValue="8", group="state") >>>>> - static final String >> RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_LENGTH_PARAM >>>>> + private static final String >>>>> RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_LENGTH_PARAM >>>>> = >>>>> >> "org.apache.myfaces.RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_LENGTH"; >>>>> - static final int >>>>> RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_LENGTH_PARAM_DEFAULT = 8; >>>>> + private static final int >>>>> RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_LENGTH_PARAM_DEFAULT = 8; >>>>> >>>>> /** >>>>> - * Sets the random class to initialize the secure random id >> generator. >>>>> + * Sets the random class to initialize the secure random id >> generator. >>>>> * By default it uses java.security.SecureRandom >>>>> */ >>>>> @JSFWebConfigParam(since="2.1.9, 2.0.15", >>>>> group="state") >>>>> - static final String >>>>> RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_SECURE_RANDOM_CLASS_PARAM >>>>> + private static final String >>>>> RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_SECURE_RANDOM_CLASS_PARAM >>>>> = >>>>> >> "org.apache.myfaces.RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_SECURE_RANDOM_CLASS"; >>>>> - >>>>> + >>>>> /** >>>>> * Sets the random provider to initialize the secure random id >> generator. >>>>> */ >>>>> @JSFWebConfigParam(since="2.1.9, 2.0.15", >>>>> group="state") >>>>> - static final String >>>>> RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_SECURE_RANDOM_PROVIDER_PARAM >>>>> + private static final String >>>>> RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_SECURE_RANDOM_PROVIDER_PARAM >>>>> = >>>>> >> "org.apache.myfaces.RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_SECURE_RANDOM_PROVIDER"; >>>>> - >>>>> + >>>>> /** >>>>> - * Sets the random algorithm to initialize the secure random >> id generator. >>>>> + * Sets the random algorithm to initialize the secure random >> id generator. >>>>> * By default is SHA1PRNG >>>>> */ >>>>> @JSFWebConfigParam(since="2.1.9, 2.0.15", >>>>> defaultValue="SHA1PRNG", group="state") >>>>> - static final String >>>>> RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_SECURE_RANDOM_ALGORITM_PARAM >>>>> + private static final String >>>>> RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_SECURE_RANDOM_ALGORITM_PARAM >>>>> = >>>>> >> "org.apache.myfaces.RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_SECURE_RANDOM_ALGORITM"; >>>>> - >>>>> - >>>>> + >>>>> + >>>>> private static final int UNCOMPRESSED_FLAG = 0; >>>>> private static final int COMPRESSED_FLAG = 1; >>>>> - >>>>> + >>>>> private static final Object[] EMPTY_STATES = new >> Object[]{null, null}; >>>>> >>>>> + //private static final int JSF_SEQUENCE_INDEX = 0; >>>>> + >>>>> private Boolean _useFlashScopePurgeViewsInSession = null; >>>>> - >>>>> + >>>>> private Integer _numberOfSequentialViewsInSession = null; >>>>> private boolean _numberOfSequentialViewsInSessionSet = false; >>>>> >>>>> + //private final KeyFactory keyFactory; >>>>> private SessionViewStorageFactory sessionViewStorageFactory; >>>>> >>>>> public ServerSideStateCacheImpl() >>>>> { >>>>> FacesContext facesContext = >> FacesContext.getCurrentInstance(); >>>>> String randomMode = >>>>> >> WebConfigParamUtils.getStringInitParameter(facesContext.getExternalContext(), >>>>> - RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_PARAM, >>>>> + RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_PARAM, >>>>> >> RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_PARAM_DEFAULT); >>>>> if >>>>> >> (RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_SECURE_RANDOM.equals(randomMode)) >>>>> { >>>>> - sessionViewStorageFactory = new >> SessionViewStorageFactory( >>>>> + //keyFactory = new >> SecureRandomKeyFactory(facesContext); >>>>> + sessionViewStorageFactory = new >> RandomSessionViewStorageFactory( >>>>> new SecureRandomKeyFactory(facesContext)); >>>>> } >>>>> else if >>>>> (RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_RANDOM.equals(randomMode)) >>>>> { >>>>> - sessionViewStorageFactory = new >> SessionViewStorageFactory( >>>>> + //keyFactory = new RandomKeyFactory(facesContext); >>>>> + sessionViewStorageFactory = new >> RandomSessionViewStorageFactory( >>>>> new RandomKeyFactory(facesContext)); >>>>> } >>>>> else >>>>> { >>>>> - sessionViewStorageFactory = new >> SessionViewStorageFactory(new >>>>> CounterKeyFactory()); >>>>> + //keyFactory = new CounterKeyFactory(); >>>>> + sessionViewStorageFactory = new >>>>> CounterSessionViewStorageFactory(new CounterKeyFactory()); >>>>> } >>>>> } >>>>> - >>>>> + >>>>> //------------------------------------- METHODS COPIED FROM >>>>> JspStateManagerImpl-------------------------------- >>>>> >>>>> protected Object getServerStateId(FacesContext facesContext, >> Object state) >>>>> @@ -285,16 +296,16 @@ class ServerSideStateCacheImpl extends S >>>>> } >>>>> >>>>> Map attributeMap = >> context.getAttributes(); >>>>> - >>>>> + >>>>> SerializedViewKey key = null; >>>>> if >> (getNumberOfSequentialViewsInSession(context.getExternalContext()) >>>>> != null && >>>>> >> getNumberOfSequentialViewsInSession(context.getExternalContext()) >>>>>> 0) >>>>> { >>>>> key = (SerializedViewKey) >>>>> attributeMap.get(RESTORED_VIEW_KEY_REQUEST_ATTR); >>>>> - >>>>> + >>>>> if (key == null ) >>>>> { >>>>> - if >>>>> (isUseFlashScopePurgeViewsInSession(context.getExternalContext()) >> && >>>>> + if >>>>> (isUseFlashScopePurgeViewsInSession(context.getExternalContext()) >> && >>>>> >>>>> Boolean.TRUE.equals(context.getExternalContext().getRequestMap() >>>>> >>>>> .get("oam.Flash.REDIRECT.PREVIOUSREQUEST"))) >>>>> { >>>>> @@ -303,7 +314,7 @@ class ServerSideStateCacheImpl extends S >>>>> } >>>>> } >>>>> } >>>>> - >>>>> + >>>>> SerializedViewKey nextKey = >>>>> getSessionViewStorageFactory().createSerializedViewKey( >>>>> context, context.getViewRoot().getViewId(), >>>>> getNextViewSequence(context)); >>>>> viewCollection.add(context, serializeView(context, >> serializedView), >>>>> nextKey, key); >>>>> @@ -339,14 +350,14 @@ class ServerSideStateCacheImpl extends S >>>>> } >>>>> } >>>>> >> attributeMap.put(RESTORED_SERIALIZED_VIEW_REQUEST_ATTR, >>>>> serializedView); >>>>> - >>>>> + >>>>> if >> (getNumberOfSequentialViewsInSession(externalContext) != null >>>>> && >>>>> >> getNumberOfSequentialViewsInSession(externalContext) > 0) >>>>> { >>>>> SerializedViewKey key = >> getSessionViewStorageFactory(). >>>>> createSerializedViewKey(context, viewId, >> sequence); >>>>> attributeMap.put(RESTORED_VIEW_KEY_REQUEST_ATTR, >> key); >>>>> - >>>>> + >>>>> if >> (isUseFlashScopePurgeViewsInSession(externalContext)) >>>>> { >>>>> >>>>> externalContext.getFlash().put(RESTORED_VIEW_KEY_REQUEST_ATTR, >> key); >>>>> @@ -418,7 +429,7 @@ class ServerSideStateCacheImpl extends S >>>>> //Object[] stateArray = (Object[]) serializedView; >>>>> >>>>> ObjectOutputStream out = new >> ObjectOutputStream(os); >>>>> - >>>>> + >>>>> out.writeObject(serializedView); >>>>> //out.writeObject(stateArray[0]); >>>>> //out.writeObject(stateArray[1]); >>>>> @@ -513,9 +524,9 @@ class ServerSideStateCacheImpl extends S >>>>> final ObjectInputStream in = new >>>>> MyFacesObjectInputStream(is); >>>>> ois = in; >>>>> Object object = null; >>>>> - if (System.getSecurityManager() != null) >>>>> + if (System.getSecurityManager() != null) >>>>> { >>>>> - object = AccessController.doPrivileged(new >>>>> PrivilegedExceptionAction() >>>>> + object = AccessController.doPrivileged(new >>>>> PrivilegedExceptionAction() >>>>> { >>>>> public Object run() throws >>>>> PrivilegedActionException, IOException, ClassNotFoundException >>>>> { >>>>> @@ -540,7 +551,7 @@ class ServerSideStateCacheImpl extends S >>>>> } >>>>> } >>>>> } >>>>> - catch (PrivilegedActionException e) >>>>> + catch (PrivilegedActionException e) >>>>> { >>>>> log.log(Level.SEVERE, "Exiting >> deserializeView - Could not >>>>> deserialize state: " + e.getMessage(), e); >>>>> return null; >>>>> @@ -577,7 +588,7 @@ class ServerSideStateCacheImpl extends S >>>>> return null; >>>>> } >>>>> } >>>>> - >>>>> + >>>>> protected static class SerializedViewCollection implements >> Serializable >>>>> { >>>>> private static final long serialVersionUID = >> -3734849062185115847L; >>>>> @@ -585,8 +596,8 @@ class ServerSideStateCacheImpl extends S >>>>> private final List _keys >>>>> = new >>>>> >> ArrayList(DEFAULT_NUMBER_OF_VIEWS_IN_SESSION); >>>>> private final Map >> _serializedViews = >>>>> new HashMap(); >>>>> - >>>>> - private final Map> SerializedViewKey> >>>>> _precedence = >>>>> + >>>>> + private final Map> SerializedViewKey> >>>>> _precedence = >>>>> new HashMap> SerializedViewKey>(); >>>>> >>>>> // old views will be hold as soft references which will be >> removed by >>>>> @@ -609,7 +620,7 @@ class ServerSideStateCacheImpl extends S >>>>> // into the map. >>>>> state = null; >>>>> } >>>>> - >>>>> + >>>>> Integer maxCount = >> getNumberOfSequentialViewsInSession(context); >>>>> if (maxCount != null) >>>>> { >>>>> @@ -647,7 +658,7 @@ class ServerSideStateCacheImpl extends S >>>>> previousKey = _precedence.get(previousKey); >>>>> count++; >>>>> } while (previousKey != null && count < >> maxCount); >>>>> - >>>>> + >>>>> if (previousKey != null) >>>>> { >>>>> SerializedViewKey keyToRemove = >> (SerializedViewKey) >>>>> previousKey; >>>>> @@ -670,7 +681,7 @@ class ServerSideStateCacheImpl extends S >>>>> { >>>>> _serializedViews.remove(keyToRemove); >>>>> } >>>>> - >>>>> + >>>>> keyToRemove = >> _precedence.remove(keyToRemove); >>>>> } while(keyToRemove != null); >>>>> } >>>>> @@ -680,11 +691,11 @@ class ServerSideStateCacheImpl extends S >>>>> while (_keys.size() > views) >>>>> { >>>>> key = _keys.remove(0); >>>>> - >>>>> + >>>>> if (maxCount != null && maxCount > 0) >>>>> { >>>>> SerializedViewKey keyToRemove = >> (SerializedViewKey) key; >>>>> - // Note in this case the key to delete is the >> oldest one, >>>>> + // Note in this case the key to delete is the >> oldest one, >>>>> // so it could be at least one precedence, but >> to be safe >>>>> // do it with a loop. >>>>> do >>>>> @@ -696,7 +707,7 @@ class ServerSideStateCacheImpl extends S >>>>> if (_serializedViews.containsKey(key) && >>>>> >>>>> >> !CACHE_OLD_VIEWS_IN_SESSION_MODE_OFF.equals(getCacheOldViewsInSessionMode(context))) >>>>> { >>>>> - >>>>> + >>>>> getOldSerializedViewsMap().put(key, >>>>> _serializedViews.remove(key)); >>>>> } >>>>> else >>>>> @@ -708,10 +719,10 @@ class ServerSideStateCacheImpl extends S >>>>> >>>>> protected Integer >> getNumberOfSequentialViewsInSession(FacesContext >>>>> context) >>>>> { >>>>> - return >>>>> >> WebConfigParamUtils.getIntegerInitParameter(context.getExternalContext(), >>>>> + return >>>>> >> WebConfigParamUtils.getIntegerInitParameter(context.getExternalContext(), >>>>> NUMBER_OF_SEQUENTIAL_VIEWS_IN_SESSION_PARAM); >>>>> } >>>>> - >>>>> + >>>>> /** >>>>> * Reads the amount (default = 20) of views to be stored >> in session. >>>>> * @see #NUMBER_OF_VIEWS_IN_SESSION_PARAM >>>>> @@ -755,7 +766,7 @@ class ServerSideStateCacheImpl extends S >>>>> FacesContext context = >> FacesContext.getCurrentInstance(); >>>>> if (_oldSerializedViews == null && context != >> null) >>>>> { >>>>> - String cacheMode = >> getCacheOldViewsInSessionMode(context); >>>>> + String cacheMode = >> getCacheOldViewsInSessionMode(context); >>>>> if >> (CACHE_OLD_VIEWS_IN_SESSION_MODE_WEAK.equals(cacheMode)) >>>>> { >>>>> _oldSerializedViews = new >>>>> ReferenceMap(AbstractReferenceMap.WEAK, AbstractReferenceMap.WEAK, >> true); >>>>> @@ -773,13 +784,13 @@ class ServerSideStateCacheImpl extends S >>>>> _oldSerializedViews = new >>>>> ReferenceMap(AbstractReferenceMap.HARD, AbstractReferenceMap.SOFT); >>>>> } >>>>> } >>>>> - >>>>> + >>>>> return _oldSerializedViews; >>>>> } >>>>> - >>>>> + >>>>> /** >>>>> * Reads the value of the >>>>> >> org.apache.myfaces.CACHE_OLD_VIEWS_IN_SESSION_MODE >>>>> context parameter. >>>>> - * >>>>> + * >>>>> * @since 1.2.5 >>>>> * @param context >>>>> * @return constant indicating caching mode >>>>> @@ -800,7 +811,7 @@ class ServerSideStateCacheImpl extends S >>>>> else if >>>>> (value.equalsIgnoreCase(CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT_WEAK)) >>>>> { >>>>> return CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT_WEAK; >>>>> - } >>>>> + } >>>>> else if >>>>> (value.equalsIgnoreCase(CACHE_OLD_VIEWS_IN_SESSION_MODE_WEAK)) >>>>> { >>>>> return CACHE_OLD_VIEWS_IN_SESSION_MODE_WEAK; >>>>> @@ -814,7 +825,7 @@ class ServerSideStateCacheImpl extends S >>>>> return CACHE_OLD_VIEWS_IN_SESSION_MODE_OFF; >>>>> } >>>>> } >>>>> - >>>>> + >>>>> public Object get(SerializedViewKey key) >>>>> { >>>>> Object value = _serializedViews.get(key); >>>>> @@ -846,7 +857,172 @@ class ServerSideStateCacheImpl extends S >>>>> } >>>>> } >>>>> >>>>> + /** >>>>> + * Base implementation where all keys used to identify the >> state of a view >>>>> should >>>>> + * extend. >>>>> + */ >>>>> + protected abstract static class SerializedViewKey implements >> Serializable >>>>> + { >>>>> + } >>>>> + >>>>> + /** >>>>> + * Implementation of SerializedViewKey, where the hashCode of >> the viewId is >>>>> used >>>>> + * and the sequenceId is a numeric value. >>>>> + */ >>>>> + private static class IntIntSerializedViewKey extends >> SerializedViewKey >>>>> + implements Serializable >>>>> + { >>>>> + private static final long serialVersionUID = >> -1170697124386063642L; >>>>> + >>>>> + private final int _viewId; >>>>> + private final int _sequenceId; >>>>> + >>>>> + public IntIntSerializedViewKey(int viewId, int sequence) >>>>> + { >>>>> + _sequenceId = sequence; >>>>> + _viewId = viewId; >>>>> + } >>>>> + >>>>> + @Override >>>>> + public boolean equals(Object obj) >>>>> + { >>>>> + if (obj == null) >>>>> + { >>>>> + return false; >>>>> + } >>>>> + if (getClass() != obj.getClass()) >>>>> + { >>>>> + return false; >>>>> + } >>>>> + final IntIntSerializedViewKey other = >> (IntIntSerializedViewKey) >>>>> obj; >>>>> + if (this._viewId != other._viewId) >>>>> + { >>>>> + return false; >>>>> + } >>>>> + if (this._sequenceId != other._sequenceId) >>>>> + { >>>>> + return false; >>>>> + } >>>>> + return true; >>>>> + } >>>>> + >>>>> + @Override >>>>> + public int hashCode() >>>>> + { >>>>> + int hash = 7; >>>>> + hash = 83 * hash + this._viewId; >>>>> + hash = 83 * hash + this._sequenceId; >>>>> + return hash; >>>>> + } >>>>> + } >>>>> + >>>>> + /** >>>>> + * Implementation of SerializedViewKey, where the hashCode of >> the viewId is >>>>> used >>>>> + * and the sequenceId is a string value. >>>>> + */ >>>>> + private static class IntByteArraySerializedViewKey extends >>>>> SerializedViewKey >>>>> + implements Serializable >>>>> + { >>>>> + private final int _viewId; >>>>> + private final byte[] _sequenceId; >>>>> + >>>>> + public IntByteArraySerializedViewKey(int viewId, byte[] >> sequence) >>>>> + { >>>>> + _sequenceId = sequence; >>>>> + _viewId = viewId; >>>>> + } >>>>> + >>>>> + @Override >>>>> + public boolean equals(Object obj) >>>>> + { >>>>> + if (obj == null) >>>>> + { >>>>> + return false; >>>>> + } >>>>> + if (getClass() != obj.getClass()) >>>>> + { >>>>> + return false; >>>>> + } >>>>> + final IntByteArraySerializedViewKey other = >>>>> (IntByteArraySerializedViewKey) obj; >>>>> + if (this._viewId != other._viewId) >>>>> + { >>>>> + return false; >>>>> + } >>>>> + if (!Arrays.equals(this._sequenceId, >> other._sequenceId)) >>>>> + { >>>>> + return false; >>>>> + } >>>>> + return true; >>>>> + } >>>>> + >>>>> + @Override >>>>> + public int hashCode() >>>>> + { >>>>> + int hash = 5; >>>>> + hash = 37 * hash + this._viewId; >>>>> + hash = 37 * hash + Arrays.hashCode(this._sequenceId); >>>>> + return hash; >>>>> + } >>>>> + } >>>>> + >>>>> + >>>>> + /** >>>>> + * Implementation of SerializedViewKey, where the viewId and >> the sequenceId >>>>> can be >>>>> + * anything. >>>>> + */ >>>>> + private static class ReferenceSerializedViewKey >> extends >>>>> SerializedViewKey >>>>> + implements Serializable >>>>> + { >>>>> + private static final long serialVersionUID = >> -1170697124386063642L; >>>>> + >>>>> + private final I _viewId; >>>>> + private final K _sequenceId; >>>>> >>>>> + public ReferenceSerializedViewKey() >>>>> + { >>>>> + _sequenceId = null; >>>>> + _viewId = null; >>>>> + } >>>>> + public ReferenceSerializedViewKey(I viewId, K sequence) >>>>> + { >>>>> + _sequenceId = sequence; >>>>> + _viewId = viewId; >>>>> + } >>>>> + >>>>> + @Override >>>>> + public boolean equals(Object obj) >>>>> + { >>>>> + if (obj == null) >>>>> + { >>>>> + return false; >>>>> + } >>>>> + if (getClass() != obj.getClass()) >>>>> + { >>>>> + return false; >>>>> + } >>>>> + final ReferenceSerializedViewKey other = >>>>> (ReferenceSerializedViewKey) obj; >>>>> + if (this._viewId != other._viewId && >> (this._viewId == null >>>>> || !this._viewId.equals(other._viewId))) >>>>> + { >>>>> + return false; >>>>> + } >>>>> + if (this._sequenceId != other._sequenceId && >>>>> + (this._sequenceId == null || >>>>> !this._sequenceId.equals(other._sequenceId))) >>>>> + { >>>>> + return false; >>>>> + } >>>>> + return true; >>>>> + } >>>>> + >>>>> + @Override >>>>> + public int hashCode() >>>>> + { >>>>> + int hash = 7; >>>>> + hash = 83 * hash + (this._viewId != null ? >> this._viewId.hashCode() >>>>> : 0); >>>>> + hash = 83 * hash + (this._sequenceId != null ? >>>>> this._sequenceId.hashCode() : 0); >>>>> + return hash; >>>>> + } >>>>> + } >>>>> + >>>>> //------------------------------------- METHOD FROM StateCache >>>>> ------------------------------------------------ >>>>> >>>>> @Override >>>>> @@ -858,12 +1034,12 @@ class ServerSideStateCacheImpl extends S >>>>> } >>>>> //save state in server session >>>>> saveSerializedViewInServletSession(facesContext, >> serializedView); >>>>> - >>>>> + >>>>> if (log.isLoggable(Level.FINEST)) >>>>> { >>>>> log.finest("Exiting saveSerializedView - >> server-side state >>>>> saving - saved state"); >>>>> } >>>>> - >>>>> + >>>>> return encodeSerializedState(facesContext, >> serializedView); >>>>> } >>>>> >>>>> @@ -886,7 +1062,7 @@ class ServerSideStateCacheImpl extends S >>>>> { >>>>> return >>>>> >> getKeyFactory(facesContext).encode(getNextViewSequence(facesContext)); >>>>> } >>>>> - >>>>> + >>>>> @Override >>>>> public boolean >> isWriteStateAfterRenderViewRequired(FacesContext >>>>> facesContext) >>>>> { >>>>> @@ -894,7 +1070,7 @@ class ServerSideStateCacheImpl extends S >>>>> } >>>>> >>>>> //------------------------------------- Custom methods >>>>> ----------------------------------------------------- >>>>> - >>>>> + >>>>> private boolean >> isUseFlashScopePurgeViewsInSession(ExternalContext >>>>> externalContext) >>>>> { >>>>> if (_useFlashScopePurgeViewsInSession == null) >>>>> @@ -904,29 +1080,372 @@ class ServerSideStateCacheImpl extends S >>>>> } >>>>> return _useFlashScopePurgeViewsInSession; >>>>> } >>>>> - >>>>> + >>>>> private Integer >> getNumberOfSequentialViewsInSession(ExternalContext >>>>> externalContext) >>>>> { >>>>> if (!_numberOfSequentialViewsInSessionSet) >>>>> { >>>>> _numberOfSequentialViewsInSession = >>>>> WebConfigParamUtils.getIntegerInitParameter( >>>>> - externalContext, >>>>> + externalContext, >>>>> NUMBER_OF_SEQUENTIAL_VIEWS_IN_SESSION_PARAM); >>>>> _numberOfSequentialViewsInSessionSet = true; >>>>> } >>>>> return _numberOfSequentialViewsInSession; >>>>> } >>>>> - >>>>> + >>>>> protected KeyFactory getKeyFactory(FacesContext facesContext) >>>>> { >>>>> //return keyFactory; >>>>> return sessionViewStorageFactory.getKeyFactory(); >>>>> } >>>>> - >>>>> + >>>>> protected SessionViewStorageFactory >> getSessionViewStorageFactory() >>>>> { >>>>> return sessionViewStorageFactory; >>>>> } >>>>> + >>>>> >>>>> + protected abstract static class KeyFactory >>>>> + { >>>>> + >>>>> + /** >>>>> + * Generates a unique key per session >>>>> + * >>>>> + * @param facesContext >>>>> + * @return >>>>> + */ >>>>> + public abstract K generateKey(FacesContext facesContext); >>>>> + >>>>> + /** >>>>> + * Encode a Key into a value that will be used as view >> state session >>>>> token >>>>> + * >>>>> + * @param key >>>>> + * @return >>>>> + */ >>>>> + public abstract V encode(K key); >>>>> >>>>> + /** >>>>> + * Decode a view state session token into a key >>>>> + * >>>>> + * @param value >>>>> + * @return >>>>> + */ >>>>> + public abstract K decode(V value); >>>>> + >>>>> + } >>>>> + >>>>> + private static class CounterKeyFactory extends >> KeyFactory>>>> String> >>>>> + { >>>>> + /** >>>>> + * Take the counter from session scope and increment >>>>> + * >>>>> + * @param facesContext >>>>> + * @return >>>>> + */ >>>>> + @Override >>>>> + public Integer generateKey(FacesContext facesContext) >>>>> + { >>>>> + ExternalContext externalContext = >>>>> facesContext.getExternalContext(); >>>>> + Object sessionObj = externalContext.getSession(true); >>>>> + Integer sequence = null; >>>>> + synchronized(sessionObj) // synchronized to increase >> sequence if >>>>> multiple requests >>>>> + // are handled at the same >> time for the >>>>> session >>>>> + { >>>>> + Map map = >>>>> externalContext.getSessionMap(); >>>>> + sequence = (Integer) >> map.get(RendererUtils.SEQUENCE_PARAM); >>>>> + if(sequence == null || sequence.intValue() == >>>>> Integer.MAX_VALUE) >>>>> + { >>>>> + sequence = Integer.valueOf(1); >>>>> + } >>>>> + else >>>>> + { >>>>> + sequence = Integer.valueOf(sequence.intValue() >> + 1); >>>>> + } >>>>> + map.put(RendererUtils.SEQUENCE_PARAM, sequence); >>>>> + } >>>>> + return sequence; >>>>> + } >>>>> + >>>>> + public String encode(Integer sequence) >>>>> + { >>>>> + return Integer.toString(sequence, >> Character.MAX_RADIX); >>>>> + } >>>>> + >>>>> + public Integer decode(String serverStateId) >>>>> + { >>>>> + return Integer.valueOf((String) serverStateId, >>>>> Character.MAX_RADIX); >>>>> + } >>>>> + } >>>>> + >>>>> + /** >>>>> + * This factory generate a key composed by a counter and a >> random number. >>>>> The >>>>> + * counter ensures uniqueness, and the random number prevents >> guess the >>>>> next >>>>> + * session token. >>>>> + */ >>>>> + private static class SecureRandomKeyFactory extends >> KeyFactory>>>> String> >>>>> + { >>>>> + private final SessionIdGenerator sessionIdGenerator; >>>>> + private final int length; >>>>> + >>>>> + public SecureRandomKeyFactory(FacesContext facesContext) >>>>> + { >>>>> + length = >>>>> >> WebConfigParamUtils.getIntegerInitParameter(facesContext.getExternalContext(), >>>>> + >> RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_LENGTH_PARAM, >>>>> + >>>>> RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_LENGTH_PARAM_DEFAULT); >>>>> + sessionIdGenerator = new SessionIdGenerator(); >>>>> + sessionIdGenerator.setSessionIdLength(length); >>>>> + String secureRandomClass = >>>>> WebConfigParamUtils.getStringInitParameter( >>>>> + facesContext.getExternalContext(), >>>>> + >>>>> RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_SECURE_RANDOM_CLASS_PARAM); >>>>> + if (secureRandomClass != null) >>>>> + { >>>>> + >> sessionIdGenerator.setSecureRandomClass(secureRandomClass); >>>>> + } >>>>> + String secureRandomProvider = >>>>> WebConfigParamUtils.getStringInitParameter( >>>>> + facesContext.getExternalContext(), >>>>> + >>>>> >> RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_SECURE_RANDOM_PROVIDER_PARAM); >>>>> + if (secureRandomProvider != null) >>>>> + { >>>>> + >>>>> sessionIdGenerator.setSecureRandomProvider(secureRandomProvider); >>>>> + } >>>>> + String secureRandomAlgorithm = >>>>> WebConfigParamUtils.getStringInitParameter( >>>>> + facesContext.getExternalContext(), >>>>> + >>>>> >> RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_SECURE_RANDOM_ALGORITM_PARAM); >>>>> + if (secureRandomAlgorithm != null) >>>>> + { >>>>> + >>>>> sessionIdGenerator.setSecureRandomAlgorithm(secureRandomAlgorithm); >>>>> + } >>>>> + } >>>>> + >>>>> + public Integer generateCounterKey(FacesContext >> facesContext) >>>>> + { >>>>> + ExternalContext externalContext = >>>>> facesContext.getExternalContext(); >>>>> + Object sessionObj = externalContext.getSession(true); >>>>> + Integer sequence = null; >>>>> + synchronized(sessionObj) // synchronized to increase >> sequence if >>>>> multiple requests >>>>> + // are handled at the same >> time for the >>>>> session >>>>> + { >>>>> + Map map = >>>>> externalContext.getSessionMap(); >>>>> + sequence = (Integer) >> map.get(RendererUtils.SEQUENCE_PARAM); >>>>> + if(sequence == null || sequence.intValue() == >>>>> Integer.MAX_VALUE) >>>>> + { >>>>> + sequence = Integer.valueOf(1); >>>>> + } >>>>> + else >>>>> + { >>>>> + sequence = Integer.valueOf(sequence.intValue() >> + 1); >>>>> + } >>>>> + map.put(RendererUtils.SEQUENCE_PARAM, sequence); >>>>> + } >>>>> + return sequence; >>>>> + } >>>>> + >>>>> + @Override >>>>> + public byte[] generateKey(FacesContext facesContext) >>>>> + { >>>>> + byte[] array = new byte[length]; >>>>> + byte[] key = new byte[length+4]; >>>>> + >>>>> + sessionIdGenerator.getRandomBytes(array); >>>>> + for (int i = 0; i < array.length; i++) >>>>> + { >>>>> + key[i] = array[i]; >>>>> + } >>>>> + int value = generateCounterKey(facesContext); >>>>> + key[array.length] = (byte) (value >>> 24); >>>>> + key[array.length+1] = (byte) (value >>> 16); >>>>> + key[array.length+2] = (byte) (value >>> 8); >>>>> + key[array.length+3] = (byte) (value); >>>>> + >>>>> + return key; >>>>> + } >>>>> + >>>>> + @Override >>>>> + public String encode(byte[] key) >>>>> + { >>>>> + return new String(Hex.encodeHex(key)); >>>>> + } >>>>> + >>>>> + @Override >>>>> + public byte[] decode(String value) >>>>> + { >>>>> + try >>>>> + { >>>>> + return Hex.decodeHex(value.toCharArray()); >>>>> + } >>>>> + catch (DecoderException ex) >>>>> + { >>>>> + // Cannot decode, ignore silently, later it will >> be handled as >>>>> + // ViewExpiredException >>>>> + } >>>>> + return null; >>>>> + } >>>>> + } >>>>> + >>>>> + private static class RandomKeyFactory extends >> KeyFactory>>>> String> >>>>> + { >>>>> + private final Random random; >>>>> + private final int length; >>>>> + >>>>> + public RandomKeyFactory(FacesContext facesContext) >>>>> + { >>>>> + length = >>>>> >> WebConfigParamUtils.getIntegerInitParameter(facesContext.getExternalContext(), >>>>> + >> RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_LENGTH_PARAM, >>>>> + >>>>> RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_LENGTH_PARAM_DEFAULT); >>>>> + random = new >> Random(((int)System.nanoTime())+this.hashCode()); >>>>> + } >>>>> + >>>>> + public Integer generateCounterKey(FacesContext >> facesContext) >>>>> + { >>>>> + ExternalContext externalContext = >>>>> facesContext.getExternalContext(); >>>>> + Object sessionObj = externalContext.getSession(true); >>>>> + Integer sequence = null; >>>>> + synchronized(sessionObj) // synchronized to increase >> sequence if >>>>> multiple requests >>>>> + // are handled at the same >> time for the >>>>> session >>>>> + { >>>>> + Map map = >>>>> externalContext.getSessionMap(); >>>>> + sequence = (Integer) >> map.get(RendererUtils.SEQUENCE_PARAM); >>>>> + if(sequence == null || sequence.intValue() == >>>>> Integer.MAX_VALUE) >>>>> + { >>>>> + sequence = Integer.valueOf(1); >>>>> + } >>>>> + else >>>>> + { >>>>> + sequence = Integer.valueOf(sequence.intValue() >> + 1); >>>>> + } >>>>> + map.put(RendererUtils.SEQUENCE_PARAM, sequence); >>>>> + } >>>>> + return sequence; >>>>> + } >>>>> + >>>>> + @Override >>>>> + public byte[] generateKey(FacesContext facesContext) >>>>> + { >>>>> + byte[] array = new byte[length]; >>>>> + byte[] key = new byte[length+4]; >>>>> + >>>>> + //sessionIdGenerator.getRandomBytes(array); >>>>> + random.nextBytes(array); >>>>> + for (int i = 0; i < array.length; i++) >>>>> + { >>>>> + key[i] = array[i]; >>>>> + } >>>>> + int value = generateCounterKey(facesContext); >>>>> + key[array.length] = (byte) (value >>> 24); >>>>> + key[array.length+1] = (byte) (value >>> 16); >>>>> + key[array.length+2] = (byte) (value >>> 8); >>>>> + key[array.length+3] = (byte) (value); >>>>> + >>>>> + return key; >>>>> + } >>>>> + >>>>> + @Override >>>>> + public String encode(byte[] key) >>>>> + { >>>>> + return new String(Hex.encodeHex(key)); >>>>> + } >>>>> + >>>>> + @Override >>>>> + public byte[] decode(String value) >>>>> + { >>>>> + try >>>>> + { >>>>> + return Hex.decodeHex(value.toCharArray()); >>>>> + } >>>>> + catch (DecoderException ex) >>>>> + { >>>>> + // Cannot decode, ignore silently, later it will >> be handled as >>>>> + // ViewExpiredException >>>>> + } >>>>> + return null; >>>>> + } >>>>> + } >>>>> + >>>>> + /** >>>>> + * >>>>> + * @param >>>>> + * @param >>>>> + * @param >>>>> + */ >>>>> + protected abstract static class SessionViewStorageFactory >> >>>> KeyFactory, K, V > >>>>> + { >>>>> + private KeyFactory keyFactory; >>>>> + >>>>> + public SessionViewStorageFactory(KeyFactory >> keyFactory) >>>>> + { >>>>> + this.keyFactory = keyFactory; >>>>> + } >>>>> + >>>>> + public KeyFactory getKeyFactory() >>>>> + { >>>>> + return keyFactory; >>>>> + } >>>>> + >>>>> + public abstract SerializedViewCollection >>>>> createSerializedViewCollection( >>>>> + FacesContext context); >>>>> + >>>>> + public abstract SerializedViewKey createSerializedViewKey( >>>>> + FacesContext facesContext, String viewId, K key); >>>>> + >>>>> + } >>>>> + >>>>> + private static class CounterSessionViewStorageFactory >>>>> + extends SessionViewStorageFactory >>>> , Integer, String> >>>>> + { >>>>> + public >> CounterSessionViewStorageFactory(KeyFactory>>>> String> keyFactory) >>>>> + { >>>>> + super(keyFactory); >>>>> + } >>>>> + >>>>> + @Override >>>>> + public SerializedViewCollection >> createSerializedViewCollection( >>>>> + FacesContext context) >>>>> + { >>>>> + return new SerializedViewCollection(); >>>>> + } >>>>> + >>>>> + @Override >>>>> + public SerializedViewKey createSerializedViewKey( >>>>> + FacesContext context, String viewId, Integer key) >>>>> + { >>>>> + if (context.isProjectStage(ProjectStage.Production)) >>>>> + { >>>>> + return new >> IntIntSerializedViewKey(viewId.hashCode(), key); >>>>> + } >>>>> + else >>>>> + { >>>>> + return new ReferenceSerializedViewKey(viewId, >> key); >>>>> + } >>>>> + } >>>>> + } >>>>> + >>>>> + private static class RandomSessionViewStorageFactory >>>>> + extends SessionViewStorageFactory > , >>>>> byte[], String> >>>>> + { >>>>> + public >> RandomSessionViewStorageFactory(KeyFactory >>>>> keyFactory) >>>>> + { >>>>> + super(keyFactory); >>>>> + } >>>>> + >>>>> + @Override >>>>> + public SerializedViewCollection >> createSerializedViewCollection( >>>>> + FacesContext context) >>>>> + { >>>>> + return new SerializedViewCollection(); >>>>> + } >>>>> + >>>>> + @Override >>>>> + public SerializedViewKey createSerializedViewKey( >>>>> + FacesContext context, String viewId, byte[] key) >>>>> + { >>>>> + if (context.isProjectStage(ProjectStage.Production)) >>>>> + { >>>>> + return new >> IntByteArraySerializedViewKey(viewId.hashCode(), >>>>> key); >>>>> + } >>>>> + else >>>>> + { >>>>> + return new ReferenceSerializedViewKey(viewId, >> key); >>>>> + } >>>>> + } >>>>> + } >>>>> } >>>>> >>