Coverage Report - org.apache.myfaces.application.viewstate.ServerSideStateCacheImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
ServerSideStateCacheImpl
0%
0/201
0%
0/118
4.65
ServerSideStateCacheImpl$1
0%
0/2
N/A
4.65
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one
 3  
  * or more contributor license agreements.  See the NOTICE file
 4  
  * distributed with this work for additional information
 5  
  * regarding copyright ownership.  The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the
 7  
  * "License"); you may not use this file except in compliance
 8  
  * with the License.  You may obtain a copy of the License at
 9  
  *
 10  
  *   http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing,
 13  
  * software distributed under the License is distributed on an
 14  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15  
  * KIND, either express or implied.  See the License for the
 16  
  * specific language governing permissions and limitations
 17  
  * under the License.
 18  
  */
 19  
 package org.apache.myfaces.application.viewstate;
 20  
 
 21  
 import java.io.ByteArrayInputStream;
 22  
 import java.io.ByteArrayOutputStream;
 23  
 import java.io.IOException;
 24  
 import java.io.InputStream;
 25  
 import java.io.ObjectInputStream;
 26  
 import java.io.ObjectOutputStream;
 27  
 import java.io.OutputStream;
 28  
 import java.security.AccessController;
 29  
 import java.security.PrivilegedActionException;
 30  
 import java.security.PrivilegedExceptionAction;
 31  
 import java.util.Map;
 32  
 import java.util.logging.Level;
 33  
 import java.util.logging.Logger;
 34  
 import java.util.zip.GZIPInputStream;
 35  
 import java.util.zip.GZIPOutputStream;
 36  
 import javax.faces.FacesWrapper;
 37  
 import javax.faces.application.StateManager;
 38  
 
 39  
 import javax.faces.context.ExternalContext;
 40  
 import javax.faces.context.FacesContext;
 41  
 import javax.faces.lifecycle.ClientWindow;
 42  
 
 43  
 import org.apache.myfaces.application.StateCache;
 44  
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
 45  
 import org.apache.myfaces.shared.config.MyfacesConfig;
 46  
 import org.apache.myfaces.shared.renderkit.RendererUtils;
 47  
 import org.apache.myfaces.shared.util.MyFacesObjectInputStream;
 48  
 import org.apache.myfaces.shared.util.WebConfigParamUtils;
 49  
 import org.apache.myfaces.spi.ViewScopeProvider;
 50  
 import org.apache.myfaces.spi.ViewScopeProviderFactory;
 51  
 import org.apache.myfaces.view.ViewScopeProxyMap;
 52  
 
 53  
 class ServerSideStateCacheImpl extends StateCache<Object, Object>
 54  
 {
 55  0
     private static final Logger log = Logger.getLogger(ServerSideStateCacheImpl.class.getName());
 56  
     
 57  0
     public static final String SERIALIZED_VIEW_SESSION_ATTR= 
 58  
         ServerSideStateCacheImpl.class.getName() + ".SERIALIZED_VIEW";
 59  
     
 60  0
     public static final String RESTORED_SERIALIZED_VIEW_REQUEST_ATTR = 
 61  
         ServerSideStateCacheImpl.class.getName() + ".RESTORED_SERIALIZED_VIEW";
 62  
     
 63  0
     public static final String RESTORED_SERIALIZED_VIEW_ID_REQUEST_ATTR = 
 64  
         ServerSideStateCacheImpl.class.getName() + ".RESTORED_SERIALIZED_VIEW_ID";
 65  0
     public static final String RESTORED_SERIALIZED_VIEW_KEY_REQUEST_ATTR = 
 66  
         ServerSideStateCacheImpl.class.getName() + ".RESTORED_SERIALIZED_VIEW_KEY";
 67  
 
 68  0
     public static final String RESTORED_VIEW_KEY_REQUEST_ATTR = 
 69  
         ServerSideStateCacheImpl.class.getName() + ".RESTORED_VIEW_KEY";
 70  
     
 71  
     public static final String NUMBER_OF_VIEWS_IN_SESSION_PARAM = MyfacesConfig.INIT_PARAM_NUMBER_OF_VIEWS_IN_SESSION;
 72  
 
 73  
     public static final String NUMBER_OF_SEQUENTIAL_VIEWS_IN_SESSION_PARAM
 74  
             = MyfacesConfig.INIT_PARAM_NUMBER_OF_SEQUENTIAL_VIEWS_IN_SESSION;
 75  
     
 76  
     public static final int DEFAULT_NUMBER_OF_VIEWS_IN_SESSION = 
 77  
             MyfacesConfig.INIT_PARAM_NUMBER_OF_VIEWS_IN_SESSION_DEFAULT;
 78  
 
 79  
     /**
 80  
      * Indicate if the state should be serialized before save it on the session. 
 81  
      * <p>
 82  
      * Only applicable if state saving method is "server" (= default).
 83  
      * If <code>true</code> (default) the state will be serialized to a byte stream before it is written to the session.
 84  
      * If <code>false</code> the state will not be serialized to a byte stream.
 85  
      * </p>
 86  
      * @deprecated 
 87  
      */
 88  
     @Deprecated
 89  
     @JSFWebConfigParam(defaultValue="false",since="1.1", expectedValues="true,false", 
 90  
         group="state", tags="performance", deprecated=true)
 91  
     public static final String SERIALIZE_STATE_IN_SESSION_PARAM = "org.apache.myfaces.SERIALIZE_STATE_IN_SESSION";
 92  
 
 93  
     /**
 94  
      * Indicates that the serialized state will be compressed before it is written to the session. By default true.
 95  
      * 
 96  
      * Only applicable if state saving method is "server" (= default) and if
 97  
      * <code>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</code> is <code>true</code> (= default).
 98  
      * If <code>true</code> (default) the serialized state will be compressed before it is written to the session.
 99  
      * If <code>false</code> the state will not be compressed.
 100  
      */
 101  
     @JSFWebConfigParam(defaultValue="true",since="1.1", expectedValues="true,false", group="state", tags="performance")
 102  
     public static final String COMPRESS_SERVER_STATE_PARAM = "org.apache.myfaces.COMPRESS_STATE_IN_SESSION";
 103  
 
 104  
     /**
 105  
      * Default value for <code>org.apache.myfaces.COMPRESS_STATE_IN_SESSION</code> context parameter.
 106  
      */
 107  
     public static final boolean DEFAULT_COMPRESS_SERVER_STATE_PARAM = true;
 108  
 
 109  
     /**
 110  
      * Default value for <code>javax.faces.SERIALIZE_SERVER_STATE and 
 111  
      * org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</code> context parameter.
 112  
      */
 113  
     public static final boolean DEFAULT_SERIALIZE_STATE_IN_SESSION = false;
 114  
 
 115  
     /**
 116  
      * This parameter has been removed from 2.2.x version.
 117  
      * 
 118  
      * @deprecated removed because it has
 119  
      */
 120  
     @Deprecated
 121  
     @JSFWebConfigParam(defaultValue="off", expectedValues="off, no, hard-soft, soft, soft-weak, weak",
 122  
                        since="1.2.5", group="state", tags="performance", deprecated = true)
 123  
     public static final String CACHE_OLD_VIEWS_IN_SESSION_MODE = "org.apache.myfaces.CACHE_OLD_VIEWS_IN_SESSION_MODE";
 124  
     
 125  
     /**
 126  
      * Allow use flash scope to keep track of the views used in session and the previous ones,
 127  
      * so server side state saving can delete old views even if POST-REDIRECT-GET pattern is used.
 128  
      * 
 129  
      * <p>
 130  
      * Only applicable if state saving method is "server" (= default).
 131  
      * The default value is false.</p>
 132  
      */
 133  
     @JSFWebConfigParam(since="2.0.6", defaultValue="false", expectedValues="true, false", group="state")
 134  
     public static final String USE_FLASH_SCOPE_PURGE_VIEWS_IN_SESSION
 135  
             = "org.apache.myfaces.USE_FLASH_SCOPE_PURGE_VIEWS_IN_SESSION";
 136  
 
 137  
     public static final String RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_NONE = "none";
 138  
     public static final String RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_SECURE_RANDOM = "secureRandom";
 139  
     public static final String RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_RANDOM = "random";
 140  
     
 141  
     /**
 142  
      * Adds a random key to the generated view state session token.
 143  
      */
 144  
     @JSFWebConfigParam(since="2.1.9, 2.0.15", expectedValues="secureRandom, random, none", 
 145  
             defaultValue="none", group="state")
 146  
     public static final String RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_PARAM
 147  
             = "org.apache.myfaces.RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN";
 148  
     public static final String RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_PARAM_DEFAULT = 
 149  
             RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_NONE;
 150  
 
 151  
     /**
 152  
      * Set the default length of the random key added to the view state session token.
 153  
      * By default is 8. 
 154  
      */
 155  
     @JSFWebConfigParam(since="2.1.9, 2.0.15", defaultValue="8", group="state")
 156  
     public static final String RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_LENGTH_PARAM 
 157  
             = "org.apache.myfaces.RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_LENGTH";
 158  
     public static final int RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_LENGTH_PARAM_DEFAULT = 8;
 159  
 
 160  
     /**
 161  
      * Sets the random class to initialize the secure random id generator. 
 162  
      * By default it uses java.security.SecureRandom
 163  
      */
 164  
     @JSFWebConfigParam(since="2.1.9, 2.0.15", group="state")
 165  
     public static final String RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_SECURE_RANDOM_CLASS_PARAM
 166  
             = "org.apache.myfaces.RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_SECURE_RANDOM_CLASS";
 167  
     
 168  
     /**
 169  
      * Sets the random provider to initialize the secure random id generator.
 170  
      */
 171  
     @JSFWebConfigParam(since="2.1.9, 2.0.15", group="state")
 172  
     public static final String RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_SECURE_RANDOM_PROVIDER_PARAM
 173  
             = "org.apache.myfaces.RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_SECURE_RANDOM_PROVIDER";
 174  
     
 175  
     /**
 176  
      * Sets the random algorithm to initialize the secure random id generator. 
 177  
      * By default is SHA1PRNG
 178  
      */
 179  
     @JSFWebConfigParam(since="2.1.9, 2.0.15", defaultValue="SHA1PRNG", group="state")
 180  
     public static final String RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_SECURE_RANDOM_ALGORITM_PARAM 
 181  
             = "org.apache.myfaces.RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_SECURE_RANDOM_ALGORITM";
 182  
     
 183  
     
 184  
     public static final int UNCOMPRESSED_FLAG = 0;
 185  
     public static final int COMPRESSED_FLAG = 1;
 186  
 
 187  0
     private Boolean _useFlashScopePurgeViewsInSession = null;
 188  
     
 189  0
     private Integer _numberOfSequentialViewsInSession = null;
 190  0
     private boolean _numberOfSequentialViewsInSessionSet = false;
 191  
 
 192  
     private SessionViewStorageFactory sessionViewStorageFactory;
 193  
 
 194  
     private CsrfSessionTokenFactory csrfSessionTokenFactory;
 195  
 
 196  
     public ServerSideStateCacheImpl()
 197  0
     {
 198  0
         FacesContext facesContext = FacesContext.getCurrentInstance();
 199  0
         String randomMode = WebConfigParamUtils.getStringInitParameter(facesContext.getExternalContext(),
 200  
                 RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_PARAM, 
 201  
                 RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_PARAM_DEFAULT);
 202  0
         if (RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_SECURE_RANDOM.equals(randomMode))
 203  
         {
 204  0
             sessionViewStorageFactory = new RandomSessionViewStorageFactory(
 205  
                     new SecureRandomKeyFactory(facesContext));
 206  
         }
 207  0
         else if (RANDOM_KEY_IN_VIEW_STATE_SESSION_TOKEN_RANDOM.equals(randomMode))
 208  
         {
 209  0
             sessionViewStorageFactory = new RandomSessionViewStorageFactory(
 210  
                     new RandomKeyFactory(facesContext));
 211  
         }
 212  
         else
 213  
         {
 214  0
             sessionViewStorageFactory = new CounterSessionViewStorageFactory(new CounterKeyFactory());
 215  
         }
 216  
         
 217  0
         String csrfRandomMode = WebConfigParamUtils.getStringInitParameter(facesContext.getExternalContext(),
 218  
                 RANDOM_KEY_IN_CSRF_SESSION_TOKEN_PARAM, 
 219  
                 RANDOM_KEY_IN_CSRF_SESSION_TOKEN_PARAM_DEFAULT);
 220  0
         if (RANDOM_KEY_IN_CSRF_SESSION_TOKEN_SECURE_RANDOM.equals(csrfRandomMode))
 221  
         {
 222  0
             csrfSessionTokenFactory = new SecureRandomCsrfSessionTokenFactory(facesContext);
 223  
         }
 224  
         else
 225  
         {
 226  0
             csrfSessionTokenFactory = new RandomCsrfSessionTokenFactory(facesContext);
 227  
         }
 228  0
     }
 229  
     
 230  
     //------------------------------------- METHODS COPIED FROM JspStateManagerImpl--------------------------------
 231  
 
 232  
     protected Object getServerStateId(FacesContext facesContext, Object state)
 233  
     {
 234  0
       if (state != null)
 235  
       {
 236  0
           return getKeyFactory(facesContext).decode((String) state);
 237  
       }
 238  0
       return null;
 239  
     }
 240  
 
 241  
     protected void saveSerializedViewInServletSession(FacesContext context,
 242  
                                                       Object serializedView)
 243  
     {
 244  0
         Map<String, Object> sessionMap = context.getExternalContext().getSessionMap();
 245  0
         SerializedViewCollection viewCollection = (SerializedViewCollection) sessionMap
 246  
                 .get(SERIALIZED_VIEW_SESSION_ATTR);
 247  0
         if (viewCollection == null)
 248  
         {
 249  0
             viewCollection = getSessionViewStorageFactory().createSerializedViewCollection(context);
 250  0
             sessionMap.put(SERIALIZED_VIEW_SESSION_ATTR, viewCollection);
 251  
         }
 252  
 
 253  0
         Map<Object,Object> attributeMap = context.getAttributes();
 254  
         
 255  0
         SerializedViewKey key = null;
 256  0
         if (getNumberOfSequentialViewsInSession(context.getExternalContext()) != null &&
 257  
             getNumberOfSequentialViewsInSession(context.getExternalContext()) > 0)
 258  
         {
 259  0
             key = (SerializedViewKey) attributeMap.get(RESTORED_VIEW_KEY_REQUEST_ATTR);
 260  
             
 261  0
             if (key == null )
 262  
             {
 263  
                 // Check if clientWindow is enabled and if the last view key is stored
 264  
                 // into session, so we can use it to chain the precedence in GET-GET
 265  
                 // cases.
 266  0
                 ClientWindow clientWindow = context.getExternalContext().getClientWindow();
 267  0
                 if (clientWindow != null)
 268  
                 {
 269  0
                     key = (SerializedViewKey) viewCollection.
 270  
                             getLastWindowKey(context, clientWindow.getId());
 271  
                 }
 272  0
                 else if (isUseFlashScopePurgeViewsInSession(context.getExternalContext()) && 
 273  
                     Boolean.TRUE.equals(context.getExternalContext().getRequestMap()
 274  
                             .get("oam.Flash.REDIRECT.PREVIOUSREQUEST")))
 275  
                 {
 276  0
                     key = (SerializedViewKey)
 277  
                             context.getExternalContext().getFlash().get(RESTORED_VIEW_KEY_REQUEST_ATTR);
 278  
                 }
 279  
             }
 280  
         }
 281  
         
 282  0
         SerializedViewKey nextKey = getSessionViewStorageFactory().createSerializedViewKey(
 283  
                 context, context.getViewRoot().getViewId(), getNextViewSequence(context));
 284  
         // Get viewScopeMapId
 285  0
         ViewScopeProxyMap viewScopeProxyMap = null;
 286  0
         Object viewMap = context.getViewRoot().getViewMap(false);
 287  0
         if (viewMap != null)
 288  
         {
 289  0
             while (viewMap != null)
 290  
             {
 291  0
                 if (viewMap instanceof ViewScopeProxyMap)
 292  
                 {
 293  0
                     viewScopeProxyMap = (ViewScopeProxyMap)viewMap;
 294  0
                     break;
 295  
                 }
 296  0
                 else if (viewMap instanceof FacesWrapper)
 297  
                 {
 298  0
                     viewMap = ((FacesWrapper)viewMap).getWrapped();
 299  
                 }
 300  
             }
 301  
 
 302  
         }
 303  0
         if (viewScopeProxyMap != null)
 304  
         {
 305  0
             ViewScopeProviderFactory factory = ViewScopeProviderFactory.getViewScopeHandlerFactory(
 306  
                 context.getExternalContext());
 307  0
             ViewScopeProvider handler = factory.getViewScopeHandler(context.getExternalContext());
 308  0
             viewCollection.put(context, serializeView(context, serializedView), nextKey, key,
 309  
                     handler, viewScopeProxyMap.getViewScopeId());
 310  0
         }
 311  
         else
 312  
         {
 313  0
             viewCollection.put(context, serializeView(context, serializedView), nextKey, key);
 314  
         }
 315  
 
 316  0
         ClientWindow clientWindow = context.getExternalContext().getClientWindow();
 317  0
         if (clientWindow != null)
 318  
         {
 319  
             //Update the last key generated for the current windowId in session map
 320  0
             viewCollection.putLastWindowKey(context, clientWindow.getId(), nextKey);
 321  
         }
 322  
         
 323  
         // replace the value to notify the container about the change
 324  0
         sessionMap.put(SERIALIZED_VIEW_SESSION_ATTR, viewCollection);
 325  0
     }
 326  
 
 327  
     protected Object getSerializedViewFromServletSession(FacesContext context, String viewId, Object sequence)
 328  
     {
 329  0
         ExternalContext externalContext = context.getExternalContext();
 330  0
         Map<Object, Object> attributeMap = context.getAttributes();
 331  0
         Object serializedView = null;
 332  0
         if (attributeMap.containsKey(RESTORED_SERIALIZED_VIEW_REQUEST_ATTR))
 333  
         {
 334  0
             serializedView = attributeMap.get(RESTORED_SERIALIZED_VIEW_REQUEST_ATTR);
 335  
         }
 336  
         else
 337  
         {
 338  0
             SerializedViewCollection viewCollection = (SerializedViewCollection) externalContext
 339  
                     .getSessionMap().get(SERIALIZED_VIEW_SESSION_ATTR);
 340  0
             if (viewCollection != null)
 341  
             {
 342  0
                 if (sequence != null)
 343  
                 {
 344  0
                     Object state = viewCollection.get(
 345  
                             getSessionViewStorageFactory().createSerializedViewKey(
 346  
                             context, viewId, sequence));
 347  0
                     if (state != null)
 348  
                     {
 349  0
                         serializedView = deserializeView(state);
 350  
                     }
 351  
                 }
 352  
             }
 353  0
             attributeMap.put(RESTORED_SERIALIZED_VIEW_REQUEST_ATTR, serializedView);
 354  
             
 355  0
             if (getNumberOfSequentialViewsInSession(externalContext) != null &&
 356  
                 getNumberOfSequentialViewsInSession(externalContext) > 0)
 357  
             {
 358  0
                 SerializedViewKey key = getSessionViewStorageFactory().
 359  
                         createSerializedViewKey(context, viewId, sequence);
 360  0
                 attributeMap.put(RESTORED_VIEW_KEY_REQUEST_ATTR, key);
 361  
                 
 362  0
                 if (isUseFlashScopePurgeViewsInSession(externalContext))
 363  
                 {
 364  0
                     externalContext.getFlash().put(RESTORED_VIEW_KEY_REQUEST_ATTR, key);
 365  0
                     externalContext.getFlash().keep(RESTORED_VIEW_KEY_REQUEST_ATTR);
 366  
                 }
 367  
             }
 368  
 
 369  0
             if (context.getPartialViewContext().isAjaxRequest() ||
 370  
                 context.getPartialViewContext().isPartialRequest())
 371  
             {
 372  
                 // Save the information used to restore. The idea is use this information later
 373  
                 // to decide if it is necessary to generate a new view sequence or use the existing
 374  
                 // one.
 375  0
                 attributeMap.put(RESTORED_SERIALIZED_VIEW_KEY_REQUEST_ATTR, sequence);
 376  0
                 attributeMap.put(RESTORED_SERIALIZED_VIEW_ID_REQUEST_ATTR, viewId);
 377  
             }
 378  
             else
 379  
             {
 380  
                 // Ensure a new sequence is used for the next view
 381  0
                 nextViewSequence(context);
 382  
             }
 383  
         }
 384  0
         return serializedView;
 385  
     }
 386  
 
 387  
     public Object getNextViewSequence(FacesContext context)
 388  
     {
 389  0
         Object sequence = context.getAttributes().get(RendererUtils.SEQUENCE_PARAM);
 390  0
         if (sequence == null)
 391  
         {
 392  0
             if (context.getPartialViewContext().isAjaxRequest() ||
 393  
                 context.getPartialViewContext().isPartialRequest())
 394  
             {
 395  0
                 String restoredViewId = (String) context.getAttributes().get(RESTORED_SERIALIZED_VIEW_ID_REQUEST_ATTR);
 396  0
                 Object restoredKey = context.getAttributes().get(RESTORED_SERIALIZED_VIEW_KEY_REQUEST_ATTR);
 397  0
                 if (restoredViewId != null && restoredKey != null)
 398  
                 {
 399  0
                     if (restoredViewId.equals(context.getViewRoot().getViewId()))
 400  
                     {
 401  
                         // The same viewId that was restored is the same that is being processed 
 402  
                         // and the request is partial or ajax. In this case we can reuse the restored
 403  
                         // key.
 404  0
                         sequence = restoredKey;
 405  
                     }
 406  
                 }
 407  
             }
 408  
             
 409  0
             if (sequence == null)
 410  
             {
 411  0
                 sequence = nextViewSequence(context);
 412  
             }
 413  0
             context.getAttributes().put(RendererUtils.SEQUENCE_PARAM, sequence);
 414  
         }
 415  0
         return sequence;
 416  
     }
 417  
 
 418  
     public Object nextViewSequence(FacesContext facescontext)
 419  
     {
 420  0
         Object sequence = getKeyFactory(facescontext).generateKey(facescontext);
 421  0
         facescontext.getAttributes().put(RendererUtils.SEQUENCE_PARAM, sequence);
 422  0
         return sequence;
 423  
     }
 424  
 
 425  
     protected Object serializeView(FacesContext context, Object serializedView)
 426  
     {
 427  0
         if (log.isLoggable(Level.FINEST))
 428  
         {
 429  0
             log.finest("Entering serializeView");
 430  
         }
 431  
 
 432  0
         if(isSerializeStateInSession(context))
 433  
         {
 434  0
             if (log.isLoggable(Level.FINEST))
 435  
             {
 436  0
                 log.finest("Processing serializeView - serialize state in session");
 437  
             }
 438  
 
 439  0
             ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
 440  
             try
 441  
             {
 442  0
                 OutputStream os = baos;
 443  0
                 if(isCompressStateInSession(context))
 444  
                 {
 445  0
                     if (log.isLoggable(Level.FINEST))
 446  
                     {
 447  0
                         log.finest("Processing serializeView - serialize compressed");
 448  
                     }
 449  
 
 450  0
                     os.write(COMPRESSED_FLAG);
 451  0
                     os = new GZIPOutputStream(os, 1024);
 452  
                 }
 453  
                 else
 454  
                 {
 455  0
                     if (log.isLoggable(Level.FINEST))
 456  
                     {
 457  0
                         log.finest("Processing serializeView - serialize uncompressed");
 458  
                     }
 459  
 
 460  0
                     os.write(UNCOMPRESSED_FLAG);
 461  
                 }
 462  
 
 463  0
                 ObjectOutputStream out = new ObjectOutputStream(os);
 464  
                 
 465  0
                 out.writeObject(serializedView);
 466  0
                 out.close();
 467  0
                 baos.close();
 468  
 
 469  0
                 if (log.isLoggable(Level.FINEST))
 470  
                 {
 471  0
                     log.finest("Exiting serializeView - serialized. Bytes : " + baos.size());
 472  
                 }
 473  0
                 return baos.toByteArray();
 474  
             }
 475  0
             catch (IOException e)
 476  
             {
 477  0
                 log.log(Level.SEVERE, "Exiting serializeView - Could not serialize state: " + e.getMessage(), e);
 478  0
                 return null;
 479  
             }
 480  
         }
 481  
 
 482  
 
 483  0
         if (log.isLoggable(Level.FINEST))
 484  
         {
 485  0
             log.finest("Exiting serializeView - do not serialize state in session.");
 486  
         }
 487  
 
 488  0
         return serializedView;
 489  
 
 490  
     }
 491  
 
 492  
     /**
 493  
      * Reads the value of the <code>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</code> context parameter.
 494  
      * @see #SERIALIZE_STATE_IN_SESSION_PARAM
 495  
      * @param context <code>FacesContext</code> for the request we are processing.
 496  
      * @return boolean true, if the server state should be serialized in the session
 497  
      */
 498  
     protected boolean isSerializeStateInSession(FacesContext context)
 499  
     {
 500  0
         String value = context.getExternalContext().getInitParameter(
 501  
                 StateManager.SERIALIZE_SERVER_STATE_PARAM_NAME);
 502  
         
 503  0
         boolean serialize = DEFAULT_SERIALIZE_STATE_IN_SESSION;
 504  0
         if (value != null)
 505  
         {
 506  0
             serialize = value.toLowerCase().equals("true");
 507  0
             return serialize;
 508  
         }
 509  
         
 510  
         // Fallback old parameter.
 511  0
         value = context.getExternalContext().getInitParameter(
 512  
                 SERIALIZE_STATE_IN_SESSION_PARAM);
 513  0
         if (value != null)
 514  
         {
 515  0
            serialize = Boolean.valueOf(value);
 516  
         }
 517  0
         return serialize;
 518  
     }
 519  
 
 520  
     /**
 521  
      * Reads the value of the <code>org.apache.myfaces.COMPRESS_STATE_IN_SESSION</code> context parameter.
 522  
      * @see #COMPRESS_SERVER_STATE_PARAM
 523  
      * @param context <code>FacesContext</code> for the request we are processing.
 524  
      * @return boolean true, if the server state steam should be compressed
 525  
      */
 526  
     protected boolean isCompressStateInSession(FacesContext context)
 527  
     {
 528  0
         String value = context.getExternalContext().getInitParameter(
 529  
                 COMPRESS_SERVER_STATE_PARAM);
 530  0
         boolean compress = DEFAULT_COMPRESS_SERVER_STATE_PARAM;
 531  0
         if (value != null)
 532  
         {
 533  0
            compress = Boolean.valueOf(value);
 534  
         }
 535  0
         return compress;
 536  
     }
 537  
 
 538  
     protected Object deserializeView(Object state)
 539  
     {
 540  0
         if (log.isLoggable(Level.FINEST))
 541  
         {
 542  0
             log.finest("Entering deserializeView");
 543  
         }
 544  
 
 545  0
         if(state instanceof byte[])
 546  
         {
 547  0
             if (log.isLoggable(Level.FINEST))
 548  
             {
 549  0
                 log.finest("Processing deserializeView - deserializing serialized state. Bytes : "
 550  
                            + ((byte[]) state).length);
 551  
             }
 552  
 
 553  
             try
 554  
             {
 555  0
                 ByteArrayInputStream bais = new ByteArrayInputStream((byte[]) state);
 556  0
                 InputStream is = bais;
 557  0
                 if(is.read() == COMPRESSED_FLAG)
 558  
                 {
 559  0
                     is = new GZIPInputStream(is);
 560  
                 }
 561  0
                 ObjectInputStream ois = null;
 562  
                 try
 563  
                 {
 564  0
                     final ObjectInputStream in = new MyFacesObjectInputStream(is);
 565  0
                     ois = in;
 566  0
                     Object object = null;
 567  0
                     if (System.getSecurityManager() != null) 
 568  
                     {
 569  0
                         object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() 
 570  0
                         {
 571  
                             public Object run() throws PrivilegedActionException, IOException, ClassNotFoundException
 572  
                             {
 573  
                                 //return new Object[] {in.readObject(), in.readObject()};
 574  0
                                 return in.readObject();
 575  
                             }
 576  
                         });
 577  
                     }
 578  
                     else
 579  
                     {
 580  
                         //object = new Object[] {in.readObject(), in.readObject()};
 581  0
                         object = in.readObject();
 582  
                     }
 583  0
                     return object;
 584  
                 }
 585  
                 finally
 586  
                 {
 587  0
                     if (ois != null)
 588  
                     {
 589  0
                         ois.close();
 590  0
                         ois = null;
 591  
                     }
 592  
                 }
 593  
             }
 594  0
             catch (PrivilegedActionException e) 
 595  
             {
 596  0
                 log.log(Level.SEVERE, "Exiting deserializeView - Could not deserialize state: " + e.getMessage(), e);
 597  0
                 return null;
 598  
             }
 599  0
             catch (IOException e)
 600  
             {
 601  0
                 log.log(Level.SEVERE, "Exiting deserializeView - Could not deserialize state: " + e.getMessage(), e);
 602  0
                 return null;
 603  
             }
 604  0
             catch (ClassNotFoundException e)
 605  
             {
 606  0
                 log.log(Level.SEVERE, "Exiting deserializeView - Could not deserialize state: " + e.getMessage(), e);
 607  0
                 return null;
 608  
             }
 609  
         }
 610  0
         else if (state instanceof Object[])
 611  
         {
 612  0
             if (log.isLoggable(Level.FINEST))
 613  
             {
 614  0
                 log.finest("Exiting deserializeView - state not serialized.");
 615  
             }
 616  
 
 617  0
             return state;
 618  
         }
 619  0
         else if(state == null)
 620  
         {
 621  0
             log.severe("Exiting deserializeView - this method should not be called with a null-state.");
 622  0
             return null;
 623  
         }
 624  
         else
 625  
         {
 626  0
             log.severe("Exiting deserializeView - this method should not be called with a state of type : "
 627  
                        + state.getClass());
 628  0
             return null;
 629  
         }
 630  
     }
 631  
     
 632  
     //------------------------------------- METHOD FROM StateCache ------------------------------------------------
 633  
 
 634  
     @Override
 635  
     public Object saveSerializedView(FacesContext facesContext, Object serializedView)
 636  
     {
 637  0
         if (log.isLoggable(Level.FINEST))
 638  
         {
 639  0
             log.finest("Processing saveSerializedView - server-side state saving - save state");
 640  
         }
 641  
         //save state in server session
 642  0
         saveSerializedViewInServletSession(facesContext, serializedView);
 643  
         
 644  0
         if (log.isLoggable(Level.FINEST))
 645  
         {
 646  0
             log.finest("Exiting saveSerializedView - server-side state saving - saved state");
 647  
         }
 648  
         
 649  0
         return encodeSerializedState(facesContext, serializedView);
 650  
     }
 651  
 
 652  
     @Override
 653  
     public Object restoreSerializedView(FacesContext facesContext, String viewId, Object viewState)
 654  
     {
 655  0
         if (log.isLoggable(Level.FINEST))
 656  
         {
 657  0
             log.finest("Restoring view from session");
 658  
         }
 659  
 
 660  0
         Object serverStateId = getServerStateId(facesContext, viewState);
 661  
 
 662  0
         return (serverStateId == null)
 663  
                 ? null
 664  
                 : getSerializedViewFromServletSession(facesContext, viewId, serverStateId);
 665  
     }
 666  
 
 667  
     public Object encodeSerializedState(FacesContext facesContext, Object serializedView)
 668  
     {
 669  0
         return getKeyFactory(facesContext).encode(getNextViewSequence(facesContext));
 670  
     }
 671  
     
 672  
     @Override
 673  
     public boolean isWriteStateAfterRenderViewRequired(FacesContext facesContext)
 674  
     {
 675  0
         return false;
 676  
     }
 677  
 
 678  
     //------------------------------------- Custom methods -----------------------------------------------------
 679  
     
 680  
     private boolean isUseFlashScopePurgeViewsInSession(ExternalContext externalContext)
 681  
     {
 682  0
         if (_useFlashScopePurgeViewsInSession == null)
 683  
         {
 684  0
             _useFlashScopePurgeViewsInSession = WebConfigParamUtils.getBooleanInitParameter(
 685  
                     externalContext, USE_FLASH_SCOPE_PURGE_VIEWS_IN_SESSION, false);
 686  
         }
 687  0
         return _useFlashScopePurgeViewsInSession;
 688  
     }
 689  
     
 690  
     private Integer getNumberOfSequentialViewsInSession(ExternalContext externalContext)
 691  
     {
 692  0
         if (!_numberOfSequentialViewsInSessionSet)
 693  
         {
 694  0
             _numberOfSequentialViewsInSession = MyfacesConfig.getCurrentInstance(externalContext)
 695  
                     .getNumberOfSequentialViewsInSession();
 696  0
             _numberOfSequentialViewsInSessionSet = true;
 697  
         }
 698  0
         return _numberOfSequentialViewsInSession;
 699  
     }
 700  
     
 701  
     protected KeyFactory getKeyFactory(FacesContext facesContext)
 702  
     {
 703  
         //return keyFactory;
 704  0
         return sessionViewStorageFactory.getKeyFactory();
 705  
     }
 706  
     
 707  
     protected SessionViewStorageFactory getSessionViewStorageFactory()
 708  
     {
 709  0
         return sessionViewStorageFactory;
 710  
     }
 711  
 
 712  
     @Override
 713  
     public String createCryptographicallyStrongTokenFromSession(FacesContext context)
 714  
     {
 715  0
         return csrfSessionTokenFactory.createCryptographicallyStrongTokenFromSession(context);
 716  
     }
 717  
 }