Coverage Report - org.apache.myfaces.application.jsp.JspStateManagerImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
JspStateManagerImpl
0%
0/376
0%
0/210
6.114
JspStateManagerImpl$1
0%
0/2
N/A
6.114
JspStateManagerImpl$SerializedViewCollection
0%
0/58
0%
0/38
6.114
JspStateManagerImpl$SerializedViewKey
0%
0/31
0%
0/22
6.114
 
 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.jsp;
 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.io.Serializable;
 29  
 import java.lang.reflect.Method;
 30  
 import java.security.AccessController;
 31  
 import java.security.PrivilegedActionException;
 32  
 import java.security.PrivilegedExceptionAction;
 33  
 import java.util.ArrayList;
 34  
 import java.util.Arrays;
 35  
 import java.util.HashMap;
 36  
 import java.util.HashSet;
 37  
 import java.util.Iterator;
 38  
 import java.util.List;
 39  
 import java.util.Map;
 40  
 import java.util.Set;
 41  
 import java.util.logging.Level;
 42  
 import java.util.logging.Logger;
 43  
 import java.util.zip.GZIPInputStream;
 44  
 import java.util.zip.GZIPOutputStream;
 45  
 
 46  
 import javax.faces.FactoryFinder;
 47  
 import javax.faces.application.StateManager;
 48  
 import javax.faces.component.NamingContainer;
 49  
 import javax.faces.component.UIComponent;
 50  
 import javax.faces.component.UIViewRoot;
 51  
 import javax.faces.context.ExternalContext;
 52  
 import javax.faces.context.FacesContext;
 53  
 import javax.faces.render.RenderKit;
 54  
 import javax.faces.render.RenderKitFactory;
 55  
 import javax.faces.render.ResponseStateManager;
 56  
 import javax.faces.view.StateManagementStrategy;
 57  
 import javax.faces.view.ViewDeclarationLanguage;
 58  
 
 59  
 import org.apache.commons.collections.map.AbstractReferenceMap;
 60  
 import org.apache.commons.collections.map.ReferenceMap;
 61  
 import org.apache.myfaces.application.MyfacesStateManager;
 62  
 import org.apache.myfaces.application.TreeStructureManager;
 63  
 import org.apache.myfaces.renderkit.MyfacesResponseStateManager;
 64  
 import org.apache.myfaces.shared.renderkit.RendererUtils;
 65  
 import org.apache.myfaces.shared.util.MyFacesObjectInputStream;
 66  
 
 67  
 /**
 68  
  * Default StateManager implementation for use when views are defined
 69  
  * via tags in JSP pages.
 70  
  *
 71  
  * @author Thomas Spiegl (latest modification by $Author: struberg $)
 72  
  * @author Manfred Geiler
 73  
  * @version $Revision: 1188643 $ $Date: 2011-10-25 08:13:09 -0500 (Tue, 25 Oct 2011) $
 74  
  */
 75  0
 public class JspStateManagerImpl extends MyfacesStateManager
 76  
 {
 77  
     //private static final Log log = LogFactory.getLog(JspStateManagerImpl.class);
 78  0
     private static final Logger log = Logger.getLogger(JspStateManagerImpl.class.getName());
 79  
     
 80  0
     private static final String SERIALIZED_VIEW_SESSION_ATTR= 
 81  
         JspStateManagerImpl.class.getName() + ".SERIALIZED_VIEW";
 82  
     
 83  0
     private static final String SERIALIZED_VIEW_REQUEST_ATTR = 
 84  
         JspStateManagerImpl.class.getName() + ".SERIALIZED_VIEW";
 85  
     
 86  0
     private static final String RESTORED_SERIALIZED_VIEW_REQUEST_ATTR = 
 87  
         JspStateManagerImpl.class.getName() + ".RESTORED_SERIALIZED_VIEW";
 88  
 
 89  
     /**
 90  
      * Only applicable if state saving method is "server" (= default).
 91  
      * Defines the amount (default = 20) of the latest views are stored in session.
 92  
      */
 93  
     private static final String NUMBER_OF_VIEWS_IN_SESSION_PARAM = "org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION";
 94  
 
 95  
     /**
 96  
      * Default value for <code>org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION</code> context parameter.
 97  
      */
 98  
     private static final int DEFAULT_NUMBER_OF_VIEWS_IN_SESSION = 20;
 99  
 
 100  
     /**
 101  
      * Only applicable if state saving method is "server" (= default).
 102  
      * If <code>true</code> (default) the state will be serialized to a byte stream before it is written to the session.
 103  
      * If <code>false</code> the state will not be serialized to a byte stream.
 104  
      */
 105  
     private static final String SERIALIZE_STATE_IN_SESSION_PARAM = "org.apache.myfaces.SERIALIZE_STATE_IN_SESSION";
 106  
 
 107  
     /**
 108  
      * Only applicable if state saving method is "server" (= default) and if
 109  
      * <code>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</code> is <code>true</code> (= default).
 110  
      * If <code>true</code> (default) the serialized state will be compressed before it is written to the session.
 111  
      * If <code>false</code> the state will not be compressed.
 112  
      */
 113  
     private static final String COMPRESS_SERVER_STATE_PARAM = "org.apache.myfaces.COMPRESS_STATE_IN_SESSION";
 114  
 
 115  
     /**
 116  
      * Default value for <code>org.apache.myfaces.COMPRESS_STATE_IN_SESSION</code> context parameter.
 117  
      */
 118  
     private static final boolean DEFAULT_COMPRESS_SERVER_STATE_PARAM = true;
 119  
 
 120  
     /**
 121  
      * Default value for <code>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</code> context parameter.
 122  
      */
 123  
     private static final boolean DEFAULT_SERIALIZE_STATE_IN_SESSION = true;
 124  
 
 125  
     /**
 126  
      * Define the way of handle old view references(views removed from session), making possible to
 127  
      * store it in a cache, so the state manager first try to get the view from the session. If is it
 128  
      * not found and soft or weak ReferenceMap is used, it try to get from it.
 129  
      * <p>
 130  
      * Only applicable if state saving method is "server" (= default).
 131  
      * </p>
 132  
      * <p>
 133  
      * The gc is responsible for remove the views, according to the rules used for soft, weak or phantom
 134  
      * references. If a key in soft and weak mode is garbage collected, its values are purged.
 135  
      * </p>
 136  
      * <p>
 137  
      * By default no cache is used, so views removed from session became phantom references.
 138  
      * </p>
 139  
      * <ul> 
 140  
      * <li> off, no: default, no cache is used</li> 
 141  
      * <li> hard-soft: use an ReferenceMap(AbstractReferenceMap.HARD, AbstractReferenceMap.SOFT)</li>
 142  
      * <li> soft: use an ReferenceMap(AbstractReferenceMap.SOFT, AbstractReferenceMap.SOFT, true) </li>
 143  
      * <li> soft-weak: use an ReferenceMap(AbstractReferenceMap.SOFT, AbstractReferenceMap.WEAK, true) </li>
 144  
      * <li> weak: use an ReferenceMap(AbstractReferenceMap.WEAK, AbstractReferenceMap.WEAK, true) </li>
 145  
      * </ul>
 146  
      * 
 147  
      */
 148  
     private static final String CACHE_OLD_VIEWS_IN_SESSION_MODE = "org.apache.myfaces.CACHE_OLD_VIEWS_IN_SESSION_MODE";
 149  
     
 150  
     /**
 151  
      * This option uses an hard-soft ReferenceMap, but it could cause a 
 152  
      * memory leak, because the keys are not removed by any method
 153  
      * (MYFACES-1660). So use with caution.
 154  
      */
 155  
     private static final String CACHE_OLD_VIEWS_IN_SESSION_MODE_HARD_SOFT = "hard-soft";
 156  
     
 157  
     private static final String CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT = "soft";
 158  
     
 159  
     private static final String CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT_WEAK = "soft-weak";
 160  
     
 161  
     private static final String CACHE_OLD_VIEWS_IN_SESSION_MODE_WEAK = "weak";
 162  
     
 163  
     private static final String CACHE_OLD_VIEWS_IN_SESSION_MODE_OFF = "off";
 164  
 
 165  
     private static final int UNCOMPRESSED_FLAG = 0;
 166  
     private static final int COMPRESSED_FLAG = 1;
 167  
 
 168  
     private static final int JSF_SEQUENCE_INDEX = 0;
 169  
 
 170  0
     private RenderKitFactory _renderKitFactory = null;
 171  
 
 172  
     public JspStateManagerImpl()
 173  0
     {
 174  0
         if (log.isLoggable(Level.FINEST))
 175  
         {
 176  0
             log.finest("New JspStateManagerImpl instance created");
 177  
         }
 178  0
     }
 179  
 
 180  
     @Override
 181  
     protected Object getComponentStateToSave(FacesContext facesContext)
 182  
     {
 183  0
         if (log.isLoggable(Level.FINEST))
 184  
         {
 185  0
             log.finest("Entering getComponentStateToSave");
 186  
         }
 187  
 
 188  0
         UIViewRoot viewRoot = facesContext.getViewRoot();
 189  0
         if (viewRoot.isTransient())
 190  
         {
 191  0
             return null;
 192  
         }
 193  
 
 194  0
         Object serializedComponentStates = viewRoot.processSaveState(facesContext);
 195  
         //Locale is a state attribute of UIViewRoot and need not be saved explicitly
 196  0
         if (log.isLoggable(Level.FINEST))
 197  
         {
 198  0
             log.finest("Exiting getComponentStateToSave");
 199  
         }
 200  0
         return serializedComponentStates;
 201  
     }
 202  
 
 203  
     /**
 204  
      * Return an object which contains info about the UIComponent type
 205  
      * of each node in the view tree. This allows an identical UIComponent
 206  
      * tree to be recreated later, though all the components will have
 207  
      * just default values for their members.
 208  
      */
 209  
     @Override
 210  
     protected Object getTreeStructureToSave(FacesContext facesContext)
 211  
     {
 212  0
         if (log.isLoggable(Level.FINEST))
 213  
         {
 214  0
             log.finest("Entering getTreeStructureToSave");
 215  
         }
 216  0
         UIViewRoot viewRoot = facesContext.getViewRoot();
 217  0
         if (viewRoot.isTransient())
 218  
         {
 219  0
             return null;
 220  
         }
 221  0
         TreeStructureManager tsm = new TreeStructureManager();
 222  0
         Object retVal = tsm.buildTreeStructureToSave(viewRoot);
 223  0
         if (log.isLoggable(Level.FINEST))
 224  
         {
 225  0
             log.finest("Exiting getTreeStructureToSave");
 226  
         }
 227  0
         return retVal;
 228  
     }
 229  
 
 230  
     /**
 231  
      * Given a tree of UIComponent objects created the default constructor
 232  
      * for each node, retrieve saved state info (from either the client or
 233  
      * the server) and walk the tree restoring the members of each node
 234  
      * from the saved state information.
 235  
      */
 236  
     @Override
 237  
     protected void restoreComponentState(FacesContext facesContext,
 238  
                                          UIViewRoot uiViewRoot,
 239  
                                          String renderKitId)
 240  
     {
 241  0
         if (log.isLoggable(Level.FINEST))
 242  
         {
 243  0
             log.finest("Entering restoreComponentState");
 244  
         }
 245  
 
 246  
         //===========================================
 247  
         // first, locate the saved state information
 248  
         //===========================================
 249  
 
 250  0
         RenderKit renderKit = getRenderKitFactory().getRenderKit(facesContext, renderKitId);
 251  0
         ResponseStateManager responseStateManager = renderKit.getResponseStateManager();
 252  
 
 253  
         Object serializedComponentStates;
 254  0
         if (isSavingStateInClient(facesContext))
 255  
         {
 256  0
             if (isLegacyResponseStateManager(responseStateManager))
 257  
             {
 258  0
                 serializedComponentStates = responseStateManager.getComponentStateToRestore(facesContext);
 259  
             }
 260  
             else
 261  
             {
 262  0
                 serializedComponentStates = responseStateManager.getState(facesContext, uiViewRoot.getViewId());
 263  
             }
 264  0
             if (serializedComponentStates == null)
 265  
             {
 266  0
                 log.severe("No serialized component state found in client request!");
 267  
                 // mark UIViewRoot invalid by resetting view id
 268  0
                 uiViewRoot.setViewId(null);
 269  0
                 return;
 270  
             }
 271  
         }
 272  
         else
 273  
         {
 274  0
             Integer serverStateId = getServerStateId((Object[])
 275  
                     responseStateManager.getState(facesContext, uiViewRoot.getViewId()));
 276  
 
 277  0
             Object[] stateObj = (Object[])( (serverStateId == null)
 278  
                     ? null
 279  
                     : getSerializedViewFromServletSession(facesContext, uiViewRoot.getViewId(), serverStateId) );
 280  
 
 281  0
             if (stateObj == null)
 282  
             {
 283  0
                  log.severe("No serialized view found in server session!");
 284  
                 // mark UIViewRoot invalid by resetting view id
 285  0
                 uiViewRoot.setViewId(null);
 286  0
                 return;
 287  
             }
 288  0
             SerializedView serializedView = new SerializedView(stateObj[0], stateObj[1]);
 289  0
             serializedComponentStates = serializedView.getState();
 290  0
             if (serializedComponentStates == null)
 291  
             {
 292  0
                 log.severe("No serialized component state found in server session!");
 293  0
                 return;
 294  
             }
 295  
         }
 296  
 
 297  0
         if (uiViewRoot.getRenderKitId() == null)
 298  
         {
 299  
             //Just to be sure...
 300  0
             uiViewRoot.setRenderKitId(renderKitId);
 301  
         }
 302  
 
 303  
         // now ask the view root component to restore its state
 304  0
         uiViewRoot.processRestoreState(facesContext, serializedComponentStates);
 305  
 
 306  0
         if (log.isLoggable(Level.FINEST))
 307  
         {
 308  0
             log.finest("Exiting restoreComponentState");
 309  
         }
 310  0
     }
 311  
 
 312  
       protected Integer getServerStateId(Object[] state)
 313  
       {
 314  0
         if (state != null)
 315  
         {
 316  0
             Object serverStateId = state[JSF_SEQUENCE_INDEX];
 317  0
             if (serverStateId != null)
 318  
             {
 319  0
                 return Integer.valueOf((String) serverStateId, Character.MAX_RADIX);
 320  
             }
 321  
         }
 322  0
         return null;
 323  
     }
 324  
 
 325  
     /**
 326  
      * See getTreeStructureToSave.
 327  
      */
 328  
     @Override
 329  
     protected UIViewRoot restoreTreeStructure(FacesContext facesContext,
 330  
                                               String viewId,
 331  
                                               String renderKitId)
 332  
     {
 333  0
         if (log.isLoggable(Level.FINEST))
 334  
         {
 335  0
             log.finest("Entering restoreTreeStructure");
 336  
         }
 337  
 
 338  0
         RenderKit rk = getRenderKitFactory().getRenderKit(facesContext, renderKitId);
 339  0
         ResponseStateManager responseStateManager = rk.getResponseStateManager();
 340  
 
 341  
         UIViewRoot uiViewRoot;
 342  0
         if (isSavingStateInClient(facesContext))
 343  
         {
 344  
             //reconstruct tree structure from request
 345  0
             Object treeStructure = responseStateManager.getTreeStructureToRestore(facesContext, viewId);
 346  0
             if (treeStructure == null)
 347  
             {
 348  0
                 if (log.isLoggable(Level.FINE))
 349  
                 {
 350  0
                     log.fine("Exiting restoreTreeStructure - No tree structure state found in client request");
 351  
                 }
 352  0
                 return null;
 353  
             }
 354  
 
 355  0
             TreeStructureManager tsm = new TreeStructureManager();
 356  0
             uiViewRoot = tsm.restoreTreeStructure(treeStructure);
 357  0
             if (log.isLoggable(Level.FINEST))
 358  
             {
 359  0
                 log.finest("Tree structure restored from client request");
 360  
             }
 361  0
         }
 362  
         else
 363  
         {
 364  
             //reconstruct tree structure from ServletSession
 365  0
             Integer serverStateId = getServerStateId((Object[]) responseStateManager.getState(facesContext, viewId));
 366  
 
 367  0
             Object[] stateObj = (Object[])( (serverStateId == null)
 368  
                     ? null
 369  
                     : getSerializedViewFromServletSession(facesContext, viewId, serverStateId) );
 370  
 
 371  0
             if (stateObj == null)
 372  
             {
 373  0
                 if (log.isLoggable(Level.FINE))
 374  
                 {
 375  0
                     log.fine("Exiting restoreTreeStructure - No serialized view found in server session!");
 376  
                 }
 377  0
                 return null;
 378  
             }
 379  
 
 380  0
             SerializedView serializedView = new SerializedView(stateObj[0], stateObj[1]);
 381  0
             Object treeStructure = serializedView.getStructure();
 382  0
             if (treeStructure == null)
 383  
             {
 384  0
                 if (log.isLoggable(Level.FINE))
 385  
                 {
 386  0
                     log.fine("Exiting restoreTreeStructure - No tree structure state found "
 387  
                              + "in server session, former UIViewRoot must have been transient");
 388  
                 }
 389  0
                 return null;
 390  
             }
 391  
 
 392  0
             TreeStructureManager tsm = new TreeStructureManager();
 393  0
             uiViewRoot = tsm.restoreTreeStructure(serializedView.getStructure());
 394  0
             if (log.isLoggable(Level.FINEST))
 395  
             {
 396  0
                 log.finest("Tree structure restored from server session");
 397  
             }
 398  
         }
 399  
 
 400  0
         if (log.isLoggable(Level.FINEST))
 401  
         {
 402  0
             log.finest("Exiting restoreTreeStructure");
 403  
         }
 404  0
         return uiViewRoot;
 405  
     }
 406  
 
 407  
     @Override
 408  
     public UIViewRoot restoreView(FacesContext facesContext, String viewId, String renderKitId)
 409  
     {
 410  0
         if (log.isLoggable(Level.FINEST))
 411  
         {
 412  0
             log.finest("Entering restoreView - viewId: " + viewId + " ; renderKitId: " + renderKitId);
 413  
         }
 414  
 
 415  0
         UIViewRoot uiViewRoot = null;
 416  
         
 417  0
         ViewDeclarationLanguage vdl = facesContext.getApplication().
 418  
             getViewHandler().getViewDeclarationLanguage(facesContext,viewId);
 419  0
         StateManagementStrategy sms = null; 
 420  0
         if (vdl != null)
 421  
         {
 422  0
             sms = vdl.getStateManagementStrategy(facesContext, viewId);
 423  
         }
 424  
         
 425  0
         if (sms != null)
 426  
         {
 427  0
             if (log.isLoggable(Level.FINEST))
 428  
             {
 429  0
                 log.finest("Redirect to StateManagementStrategy: " + sms.getClass().getName());
 430  
             }
 431  
             
 432  0
             uiViewRoot = sms.restoreView(facesContext, viewId, renderKitId);
 433  
         }
 434  
         else
 435  
         {
 436  0
             RenderKit renderKit = getRenderKitFactory().getRenderKit(facesContext, renderKitId);
 437  0
             ResponseStateManager responseStateManager = renderKit.getResponseStateManager();
 438  
 
 439  
             Object state;
 440  0
             if (isSavingStateInClient(facesContext))
 441  
             {
 442  0
                 if (log.isLoggable(Level.FINEST))
 443  
                 {
 444  0
                     log.finest("Restoring view from client");
 445  
                 }
 446  
 
 447  0
                 state = responseStateManager.getState(facesContext, viewId);
 448  
             }
 449  
             else
 450  
             {
 451  0
                 if (log.isLoggable(Level.FINEST))
 452  
                 {
 453  0
                     log.finest("Restoring view from session");
 454  
                 }
 455  
 
 456  0
                 Integer serverStateId
 457  
                         = getServerStateId((Object[]) responseStateManager.getState(facesContext, viewId));
 458  
 
 459  0
                 state = (serverStateId == null)
 460  
                         ? null
 461  
                         : getSerializedViewFromServletSession(facesContext, viewId, serverStateId);
 462  
             }
 463  
 
 464  0
             if (state != null)
 465  
             {
 466  0
                 Object[] stateArray = (Object[])state;
 467  0
                 TreeStructureManager tsm = new TreeStructureManager();
 468  0
                 uiViewRoot = tsm.restoreTreeStructure(stateArray[0]);
 469  
 
 470  0
                 if (uiViewRoot != null)
 471  
                 {
 472  0
                     facesContext.setViewRoot (uiViewRoot);
 473  0
                     uiViewRoot.processRestoreState(facesContext, stateArray[1]);
 474  
                 }
 475  
             }            
 476  
         }
 477  0
         if (log.isLoggable(Level.FINEST))
 478  
         {
 479  0
             log.finest("Exiting restoreView - " + viewId);
 480  
         }
 481  
 
 482  0
         return uiViewRoot;
 483  
     }
 484  
 
 485  
     /**
 486  
      * Wrap the original method and redirect to VDL StateManagementStrategy when
 487  
      * necessary
 488  
      */
 489  
     @Override
 490  
     public Object saveView(FacesContext facesContext)
 491  
     {
 492  0
         UIViewRoot uiViewRoot = facesContext.getViewRoot();
 493  
         
 494  0
         String viewId = uiViewRoot.getViewId();
 495  0
         ViewDeclarationLanguage vdl = facesContext.getApplication().
 496  
             getViewHandler().getViewDeclarationLanguage(facesContext,viewId);
 497  
         try
 498  
         {
 499  0
             facesContext.getAttributes().put(StateManager.IS_SAVING_STATE, Boolean.TRUE);
 500  0
             if (vdl != null)
 501  
             {
 502  0
                 StateManagementStrategy sms = vdl.getStateManagementStrategy(facesContext, viewId);
 503  
                 
 504  0
                 if (sms != null)
 505  
                 {
 506  0
                     if (log.isLoggable(Level.FINEST))
 507  
                     {
 508  0
                         log.finest("Calling saveView of StateManagementStrategy: " + sms.getClass().getName());
 509  
                     }
 510  
                     
 511  0
                     return sms.saveView(facesContext);
 512  
                 }
 513  
             }
 514  
     
 515  
             // In StateManagementStrategy.saveView there is a check for transient at
 516  
             // start, but the same applies for VDL without StateManagementStrategy,
 517  
             // so this should be checked before call parent (note that parent method
 518  
             // does not do this check).
 519  0
             if (uiViewRoot.isTransient())
 520  
             {
 521  0
                 return null;
 522  
             }
 523  
     
 524  0
             return super.saveView(facesContext);
 525  
         }
 526  
         finally
 527  
         {
 528  0
             facesContext.getAttributes().remove(StateManager.IS_SAVING_STATE);
 529  
         }
 530  
     }
 531  
     
 532  
     @Override
 533  
     public SerializedView saveSerializedView(FacesContext facesContext) throws IllegalStateException
 534  
     {
 535  0
         if (log.isLoggable(Level.FINEST))
 536  
         {
 537  0
             log.finest("Entering saveSerializedView");
 538  
         }
 539  
 
 540  0
         checkForDuplicateIds(facesContext, facesContext.getViewRoot(), new HashSet<String>());
 541  
 
 542  0
         if (log.isLoggable(Level.FINEST))
 543  
         {
 544  0
             log.finest("Processing saveSerializedView - Checked for duplicate Ids");
 545  
         }
 546  
 
 547  0
         ExternalContext externalContext = facesContext.getExternalContext();
 548  
 
 549  
         // SerializedView already created before within this request?
 550  0
         Object serializedView = externalContext.getRequestMap()
 551  
                                                             .get(SERIALIZED_VIEW_REQUEST_ATTR);
 552  0
         if (serializedView == null)
 553  
         {
 554  0
             if (log.isLoggable(Level.FINEST))
 555  
             {
 556  0
                 log.finest("Processing saveSerializedView - create new serialized view");
 557  
             }
 558  
 
 559  
             // first call to saveSerializedView --> create SerializedView
 560  0
             Object treeStruct = getTreeStructureToSave(facesContext);
 561  0
             Object compStates = getComponentStateToSave(facesContext);
 562  0
             serializedView = new Object[] {treeStruct, compStates};
 563  0
             externalContext.getRequestMap().put(SERIALIZED_VIEW_REQUEST_ATTR,
 564  
                                                 serializedView);
 565  
 
 566  0
             if (log.isLoggable(Level.FINEST))
 567  
             {
 568  0
                 log.finest("Processing saveSerializedView - new serialized view created");
 569  
             }
 570  
         }
 571  
 
 572  0
         Object[] serializedViewArray = (Object[]) serializedView;
 573  
 
 574  0
         if (!isSavingStateInClient(facesContext))
 575  
         {
 576  0
             if (log.isLoggable(Level.FINEST))
 577  
             {
 578  0
                 log.finest("Processing saveSerializedView - server-side state saving - save state");
 579  
             }
 580  
             //save state in server session
 581  0
             saveSerializedViewInServletSession(facesContext, serializedView);
 582  
 
 583  0
             if (log.isLoggable(Level.FINEST))
 584  
             {
 585  0
                 log.finest("Exiting saveSerializedView - server-side state saving - saved state");
 586  
             }
 587  0
             return new SerializedView(serializedViewArray[0], new Object[0]);
 588  
         }
 589  
 
 590  0
         if (log.isLoggable(Level.FINEST))
 591  
         {
 592  0
             log.finest("Exiting saveSerializedView - client-side state saving");
 593  
         }
 594  
 
 595  0
         return new SerializedView(serializedViewArray[0], serializedViewArray[1]);
 596  
     }
 597  
 
 598  
     private static void checkForDuplicateIds(FacesContext context,
 599  
                                              UIComponent component,
 600  
                                              Set<String> ids)
 601  
     {
 602  0
         String id = component.getId();
 603  0
         if (id != null && !ids.add(id))
 604  
         {
 605  0
             throw new IllegalStateException("Client-id : " + id +
 606  
                                             " is duplicated in the faces tree. Component : " + 
 607  
                                             component.getClientId(context)+", path: " +
 608  
                                             getPathToComponent(component));
 609  
         }
 610  
         
 611  0
         if (component instanceof NamingContainer)
 612  
         {
 613  0
             ids = new HashSet<String>();
 614  
         }
 615  
         
 616  0
         Iterator<UIComponent> it = component.getFacetsAndChildren();
 617  0
         while (it.hasNext())
 618  
         {
 619  0
             UIComponent kid = it.next();
 620  0
             checkForDuplicateIds(context, kid, ids);
 621  0
         }
 622  0
     }
 623  
 
 624  
     private static String getPathToComponent(UIComponent component)
 625  
     {
 626  0
         StringBuffer buf = new StringBuffer();
 627  
 
 628  0
         if(component == null)
 629  
         {
 630  0
             buf.append("{Component-Path : ");
 631  0
             buf.append("[null]}");
 632  0
             return buf.toString();
 633  
         }
 634  
 
 635  0
         getPathToComponent(component,buf);
 636  
 
 637  0
         buf.insert(0,"{Component-Path : ");
 638  0
         buf.append("}");
 639  
 
 640  0
         return buf.toString();
 641  
     }
 642  
 
 643  
     private static void getPathToComponent(UIComponent component, StringBuffer buf)
 644  
     {
 645  0
         if(component == null)
 646  
         {
 647  0
             return;
 648  
         }
 649  
 
 650  0
         StringBuffer intBuf = new StringBuffer();
 651  
 
 652  0
         intBuf.append("[Class: ");
 653  0
         intBuf.append(component.getClass().getName());
 654  0
         if(component instanceof UIViewRoot)
 655  
         {
 656  0
             intBuf.append(",ViewId: ");
 657  0
             intBuf.append(((UIViewRoot) component).getViewId());
 658  
         }
 659  
         else
 660  
         {
 661  0
             intBuf.append(",Id: ");
 662  0
             intBuf.append(component.getId());
 663  
         }
 664  0
         intBuf.append("]");
 665  
 
 666  0
         buf.insert(0,intBuf.toString());
 667  
 
 668  0
         getPathToComponent(component.getParent(),buf);
 669  0
     }
 670  
 
 671  
     @Override
 672  
     public void writeState(FacesContext facesContext,
 673  
                            SerializedView serializedView) throws IOException
 674  
     {
 675  0
         if (log.isLoggable(Level.FINEST))
 676  
         {
 677  0
             log.finest("Entering writeState");
 678  
         }
 679  
 
 680  0
         UIViewRoot uiViewRoot = facesContext.getViewRoot();
 681  
         //save state in response (client)
 682  0
         RenderKit renderKit = getRenderKitFactory().getRenderKit(facesContext, uiViewRoot.getRenderKitId());
 683  0
         ResponseStateManager responseStateManager = renderKit.getResponseStateManager();
 684  
 
 685  0
         if (isLegacyResponseStateManager(responseStateManager))
 686  
         {
 687  0
             responseStateManager.writeState(facesContext, serializedView);
 688  
         }
 689  0
         else if (!isSavingStateInClient(facesContext))
 690  
         {
 691  0
             Object[] state = new Object[2];
 692  0
             state[JSF_SEQUENCE_INDEX] = Integer.toString(getNextViewSequence(facesContext), Character.MAX_RADIX);
 693  0
             responseStateManager.writeState(facesContext, state);
 694  0
         }
 695  
         else
 696  
         {
 697  0
             Object[] state = new Object[2];
 698  0
             state[0] = serializedView.getStructure();
 699  0
             state[1] = serializedView.getState();
 700  0
             responseStateManager.writeState(facesContext, state);
 701  
         }
 702  
 
 703  0
         if (log.isLoggable(Level.FINEST))
 704  
         {
 705  0
             log.finest("Exiting writeState");
 706  
         }
 707  
 
 708  0
     }
 709  
 
 710  
     @Override
 711  
     public String getViewState(FacesContext facesContext)
 712  
     {
 713  0
         UIViewRoot uiViewRoot = facesContext.getViewRoot();
 714  0
         String viewId = uiViewRoot.getViewId();
 715  0
         ViewDeclarationLanguage vdl
 716  
                 = facesContext.getApplication().getViewHandler().getViewDeclarationLanguage(facesContext,viewId);
 717  0
         if (vdl != null)
 718  
         {
 719  0
             StateManagementStrategy sms = vdl.getStateManagementStrategy(facesContext, viewId);
 720  
             
 721  0
             if (sms != null)
 722  
             {
 723  0
                 if (log.isLoggable(Level.FINEST))
 724  
                 {
 725  0
                     log.finest("Calling saveView of StateManagementStrategy from getViewState: "
 726  
                                + sms.getClass().getName());
 727  
                 }
 728  
                 
 729  0
                 return facesContext.getRenderKit().getResponseStateManager().
 730  
                         getViewState(facesContext, saveView(facesContext));
 731  
             }
 732  
         }
 733  0
         Object[] savedState = (Object[]) saveView(facesContext);
 734  
         
 735  0
         if (!isSavingStateInClient(facesContext))
 736  
         {
 737  0
             Object[] state = new Object[2];
 738  0
             state[JSF_SEQUENCE_INDEX] = Integer.toString(getNextViewSequence(facesContext), Character.MAX_RADIX);
 739  0
             return facesContext.getRenderKit().getResponseStateManager().getViewState(facesContext, state);
 740  
         }
 741  
         else
 742  
         {
 743  0
             return facesContext.getRenderKit().getResponseStateManager().getViewState(facesContext, savedState);
 744  
         }
 745  
     }
 746  
 
 747  
     /**
 748  
      * MyFaces extension
 749  
      * @param facesContext
 750  
      * @param serializedView
 751  
      * @throws IOException
 752  
      */
 753  
     @Override
 754  
     public void writeStateAsUrlParams(FacesContext facesContext,
 755  
                                       SerializedView serializedView) throws IOException
 756  
     {
 757  0
         if (log.isLoggable(Level.FINEST))
 758  
         {
 759  0
             log.finest("Entering writeStateAsUrlParams");
 760  
         }
 761  
 
 762  0
         if (isSavingStateInClient(facesContext))
 763  
         {
 764  0
             if (log.isLoggable(Level.FINEST))
 765  
             {
 766  0
                 log.finest("Processing writeStateAsUrlParams - client-side state saving writing state");
 767  
             }
 768  
 
 769  0
             UIViewRoot uiViewRoot = facesContext.getViewRoot();
 770  
             //save state in response (client)
 771  0
             RenderKit renderKit = getRenderKitFactory().getRenderKit(facesContext, uiViewRoot.getRenderKitId());
 772  0
             ResponseStateManager responseStateManager = renderKit.getResponseStateManager();
 773  0
             if (responseStateManager instanceof MyfacesResponseStateManager)
 774  
             {
 775  0
                 ((MyfacesResponseStateManager)responseStateManager).writeStateAsUrlParams(facesContext,
 776  
                                                                                           serializedView);
 777  
             }
 778  
             else
 779  
             {
 780  0
                 log.severe("ResponseStateManager of render kit " + uiViewRoot.getRenderKitId()
 781  
                         + " is no MyfacesResponseStateManager and does not support saving state in url parameters.");
 782  
             }
 783  
         }
 784  
 
 785  0
         if (log.isLoggable(Level.FINEST))
 786  
         {
 787  0
             log.finest("Exiting writeStateAsUrlParams");
 788  
         }
 789  0
     }
 790  
 
 791  
     //helpers
 792  
 
 793  
     protected RenderKitFactory getRenderKitFactory()
 794  
     {
 795  0
         if (_renderKitFactory == null)
 796  
         {
 797  0
             _renderKitFactory = (RenderKitFactory)FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
 798  
         }
 799  0
         return _renderKitFactory;
 800  
     }
 801  
 
 802  
     protected void saveSerializedViewInServletSession(FacesContext context,
 803  
                                                       Object serializedView)
 804  
     {
 805  0
         Map<String, Object> sessionMap = context.getExternalContext().getSessionMap();
 806  0
         SerializedViewCollection viewCollection = (SerializedViewCollection) sessionMap
 807  
                 .get(SERIALIZED_VIEW_SESSION_ATTR);
 808  0
         if (viewCollection == null)
 809  
         {
 810  0
             viewCollection = new SerializedViewCollection();
 811  0
             sessionMap.put(SERIALIZED_VIEW_SESSION_ATTR, viewCollection);
 812  
         }
 813  0
         viewCollection.add(context, serializeView(context, serializedView));
 814  
         // replace the value to notify the container about the change
 815  0
         sessionMap.put(SERIALIZED_VIEW_SESSION_ATTR, viewCollection);
 816  0
     }
 817  
 
 818  
     protected Object getSerializedViewFromServletSession(FacesContext context, String viewId, Integer sequence)
 819  
     {
 820  0
         ExternalContext externalContext = context.getExternalContext();
 821  0
         Map<String, Object> requestMap = externalContext.getRequestMap();
 822  0
         Object serializedView = null;
 823  0
         if (requestMap.containsKey(RESTORED_SERIALIZED_VIEW_REQUEST_ATTR))
 824  
         {
 825  0
             serializedView = requestMap.get(RESTORED_SERIALIZED_VIEW_REQUEST_ATTR);
 826  
         }
 827  
         else
 828  
         {
 829  0
             SerializedViewCollection viewCollection = (SerializedViewCollection) externalContext
 830  
                     .getSessionMap().get(SERIALIZED_VIEW_SESSION_ATTR);
 831  0
             if (viewCollection != null)
 832  
             {
 833  
                 /*
 834  
                 String sequenceStr = externalContext.getRequestParameterMap().get(
 835  
                        RendererUtils.SEQUENCE_PARAM);
 836  
                 Integer sequence = null;
 837  
                 if (sequenceStr == null)
 838  
                 {
 839  
                     // use latest sequence
 840  
                     Map map = externalContext.getSessionMap();
 841  
                     sequence = (Integer) map.get(RendererUtils.SEQUENCE_PARAM);
 842  
                 }
 843  
                 else
 844  
                 {
 845  
                     sequence = new Integer(sequenceStr);
 846  
                 }
 847  
                 */
 848  0
                 if (sequence != null)
 849  
                 {
 850  0
                     Object state = viewCollection.get(sequence, viewId);
 851  0
                     if (state != null)
 852  
                     {
 853  0
                         serializedView = deserializeView(state);
 854  
                     }
 855  
                 }
 856  
             }
 857  0
             requestMap.put(RESTORED_SERIALIZED_VIEW_REQUEST_ATTR, serializedView);
 858  0
             nextViewSequence(context);
 859  
         }
 860  0
         return serializedView;
 861  
     }
 862  
 
 863  
     protected int getNextViewSequence(FacesContext context)
 864  
     {
 865  0
         ExternalContext externalContext = context.getExternalContext();
 866  
 
 867  0
         if (!externalContext.getRequestMap().containsKey(RendererUtils.SEQUENCE_PARAM))
 868  
         {
 869  0
             nextViewSequence(context);
 870  
         }
 871  
 
 872  0
         Integer sequence = (Integer) externalContext.getRequestMap().get(RendererUtils.SEQUENCE_PARAM);
 873  0
         return sequence.intValue();
 874  
     }
 875  
 
 876  
     protected void nextViewSequence(FacesContext facescontext)
 877  
     {
 878  0
         ExternalContext externalContext = facescontext.getExternalContext();
 879  0
         Object sessionObj = externalContext.getSession(true);
 880  0
         synchronized(sessionObj) // synchronized to increase sequence if multiple requests
 881  
                                  // are handled at the same time for the session
 882  
         {
 883  0
             Map<String, Object> map = externalContext.getSessionMap();
 884  0
             Integer sequence = (Integer) map.get(RendererUtils.SEQUENCE_PARAM);
 885  0
             if(sequence == null || sequence.intValue() == Integer.MAX_VALUE)
 886  
             {
 887  0
                 sequence = Integer.valueOf(1);
 888  
             }
 889  
             else
 890  
             {
 891  0
                 sequence = Integer.valueOf(sequence.intValue() + 1);
 892  
             }
 893  0
             map.put(RendererUtils.SEQUENCE_PARAM, sequence);
 894  0
             externalContext.getRequestMap().put(RendererUtils.SEQUENCE_PARAM, sequence);
 895  0
         }
 896  0
     }
 897  
 
 898  
     protected Object serializeView(FacesContext context, Object serializedView)
 899  
     {
 900  0
         if (log.isLoggable(Level.FINEST))
 901  
         {
 902  0
             log.finest("Entering serializeView");
 903  
         }
 904  
 
 905  0
         if(isSerializeStateInSession(context))
 906  
         {
 907  0
             if (log.isLoggable(Level.FINEST))
 908  
             {
 909  0
                 log.finest("Processing serializeView - serialize state in session");
 910  
             }
 911  
 
 912  0
             ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
 913  
             try
 914  
             {
 915  0
                 OutputStream os = baos;
 916  0
                 if(isCompressStateInSession(context))
 917  
                 {
 918  0
                     if (log.isLoggable(Level.FINEST))
 919  
                     {
 920  0
                         log.finest("Processing serializeView - serialize compressed");
 921  
                     }
 922  
 
 923  0
                     os.write(COMPRESSED_FLAG);
 924  0
                     os = new GZIPOutputStream(os, 1024);
 925  
                 }
 926  
                 else
 927  
                 {
 928  0
                     if (log.isLoggable(Level.FINEST))
 929  
                     {
 930  0
                         log.finest("Processing serializeView - serialize uncompressed");
 931  
                     }
 932  
 
 933  0
                     os.write(UNCOMPRESSED_FLAG);
 934  
                 }
 935  
 
 936  0
                 Object[] stateArray = (Object[]) serializedView;
 937  
 
 938  0
                 ObjectOutputStream out = new ObjectOutputStream(os);
 939  0
                 out.writeObject(stateArray[0]);
 940  0
                 out.writeObject(stateArray[1]);
 941  0
                 out.close();
 942  0
                 baos.close();
 943  
 
 944  0
                 if (log.isLoggable(Level.FINEST))
 945  
                 {
 946  0
                     log.finest("Exiting serializeView - serialized. Bytes : " + baos.size());
 947  
                 }
 948  0
                 return baos.toByteArray();
 949  
             }
 950  0
             catch (IOException e)
 951  
             {
 952  0
                 log.log(Level.SEVERE, "Exiting serializeView - Could not serialize state: " + e.getMessage(), e);
 953  0
                 return null;
 954  
             }
 955  
         }
 956  
 
 957  
 
 958  0
         if (log.isLoggable(Level.FINEST))
 959  
         {
 960  0
             log.finest("Exiting serializeView - do not serialize state in session.");
 961  
         }
 962  
 
 963  0
         return serializedView;
 964  
 
 965  
     }
 966  
 
 967  
     /**
 968  
      * Reads the value of the <code>org.apache.myfaces.SERIALIZE_STATE_IN_SESSION</code> context parameter.
 969  
      * @see #SERIALIZE_STATE_IN_SESSION_PARAM
 970  
      * @param context <code>FacesContext</code> for the request we are processing.
 971  
      * @return boolean true, if the server state should be serialized in the session
 972  
      */
 973  
     protected boolean isSerializeStateInSession(FacesContext context)
 974  
     {
 975  0
         String value = context.getExternalContext().getInitParameter(
 976  
                 SERIALIZE_STATE_IN_SESSION_PARAM);
 977  0
         boolean serialize = DEFAULT_SERIALIZE_STATE_IN_SESSION;
 978  0
         if (value != null)
 979  
         {
 980  0
            serialize = Boolean.valueOf(value);
 981  
         }
 982  0
         return serialize;
 983  
     }
 984  
 
 985  
     /**
 986  
      * Reads the value of the <code>org.apache.myfaces.COMPRESS_STATE_IN_SESSION</code> context parameter.
 987  
      * @see #COMPRESS_SERVER_STATE_PARAM
 988  
      * @param context <code>FacesContext</code> for the request we are processing.
 989  
      * @return boolean true, if the server state steam should be compressed
 990  
      */
 991  
     protected boolean isCompressStateInSession(FacesContext context)
 992  
     {
 993  0
         String value = context.getExternalContext().getInitParameter(
 994  
                 COMPRESS_SERVER_STATE_PARAM);
 995  0
         boolean compress = DEFAULT_COMPRESS_SERVER_STATE_PARAM;
 996  0
         if (value != null)
 997  
         {
 998  0
            compress = Boolean.valueOf(value);
 999  
         }
 1000  0
         return compress;
 1001  
     }
 1002  
 
 1003  
     protected Object deserializeView(Object state)
 1004  
     {
 1005  0
         if (log.isLoggable(Level.FINEST))
 1006  
         {
 1007  0
             log.finest("Entering deserializeView");
 1008  
         }
 1009  
 
 1010  0
         if(state instanceof byte[])
 1011  
         {
 1012  0
             if (log.isLoggable(Level.FINEST))
 1013  
             {
 1014  0
                 log.finest("Processing deserializeView - deserializing serialized state. Bytes : "
 1015  
                            + ((byte[]) state).length);
 1016  
             }
 1017  
 
 1018  
             try
 1019  
             {
 1020  0
                 ByteArrayInputStream bais = new ByteArrayInputStream((byte[]) state);
 1021  0
                 InputStream is = bais;
 1022  0
                 if(is.read() == COMPRESSED_FLAG)
 1023  
                 {
 1024  0
                     is = new GZIPInputStream(is);
 1025  
                 }
 1026  0
                 ObjectInputStream ois = null;
 1027  
                 try
 1028  
                 {
 1029  0
                     final ObjectInputStream in = new MyFacesObjectInputStream(is);
 1030  0
                     ois = in;
 1031  0
                     Object object = null;
 1032  0
                     if (System.getSecurityManager() != null) 
 1033  
                     {
 1034  0
                         object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object []>() 
 1035  0
                         {
 1036  
                             public Object[] run() throws PrivilegedActionException, IOException, ClassNotFoundException
 1037  
                             {
 1038  0
                                 return new Object[] {in.readObject(), in.readObject()};
 1039  
                             }
 1040  
                         });
 1041  
                     }
 1042  
                     else
 1043  
                     {
 1044  0
                         object = new Object[] {in.readObject(), in.readObject()};
 1045  
                     }
 1046  0
                     return object;
 1047  
                 }
 1048  
                 finally
 1049  
                 {
 1050  0
                     if (ois != null)
 1051  
                     {
 1052  0
                         ois.close();
 1053  0
                         ois = null;
 1054  
                     }
 1055  
                 }
 1056  
             }
 1057  0
             catch (PrivilegedActionException e) 
 1058  
             {
 1059  0
                 log.log(Level.SEVERE, "Exiting deserializeView - Could not deserialize state: " + e.getMessage(), e);
 1060  0
                 return null;
 1061  
             }
 1062  0
             catch (IOException e)
 1063  
             {
 1064  0
                 log.log(Level.SEVERE, "Exiting deserializeView - Could not deserialize state: " + e.getMessage(), e);
 1065  0
                 return null;
 1066  
             }
 1067  0
             catch (ClassNotFoundException e)
 1068  
             {
 1069  0
                 log.log(Level.SEVERE, "Exiting deserializeView - Could not deserialize state: " + e.getMessage(), e);
 1070  0
                 return null;
 1071  
             }
 1072  
         }
 1073  0
         else if (state instanceof Object[])
 1074  
         {
 1075  0
             if (log.isLoggable(Level.FINEST))
 1076  
             {
 1077  0
                 log.finest("Exiting deserializeView - state not serialized.");
 1078  
             }
 1079  
 
 1080  0
             return state;
 1081  
         }
 1082  0
         else if(state == null)
 1083  
         {
 1084  0
             log.severe("Exiting deserializeView - this method should not be called with a null-state.");
 1085  0
             return null;
 1086  
         }
 1087  
         else
 1088  
         {
 1089  0
             log.severe("Exiting deserializeView - this method should not be called with a state of type : "
 1090  
                        + state.getClass());
 1091  0
             return null;
 1092  
         }
 1093  
     }
 1094  
 
 1095  
     private boolean isLegacyResponseStateManager(ResponseStateManager instance)
 1096  
     {
 1097  
 
 1098  0
         Method[] methods = instance.getClass().getMethods();
 1099  0
         for (Method m : methods)
 1100  
         {
 1101  0
             if (m.getName().equals("getState") &&
 1102  
                     Arrays.equals(m.getParameterTypes(),new Class[] {FacesContext.class, String.class}))
 1103  
             {
 1104  0
                  return false;
 1105  
             }
 1106  
         }
 1107  
 
 1108  0
         return true;
 1109  
     }
 1110  
 
 1111  0
     protected static class SerializedViewCollection implements Serializable
 1112  
     {
 1113  
         private static final long serialVersionUID = -3734849062185115847L;
 1114  
 
 1115  0
         private final List<Object> _keys = new ArrayList<Object>(DEFAULT_NUMBER_OF_VIEWS_IN_SESSION);
 1116  0
         private final Map<Object, Object> _serializedViews = new HashMap<Object, Object>();
 1117  
 
 1118  
         // old views will be hold as soft references which will be removed by
 1119  
         // the garbage collector if free memory is low
 1120  0
         private transient Map<Object, Object> _oldSerializedViews = null;
 1121  
 
 1122  
         public synchronized void add(FacesContext context, Object state)
 1123  
         {
 1124  0
             Object key = new SerializedViewKey(context);
 1125  0
             _serializedViews.put(key, state);
 1126  
 
 1127  0
             while (_keys.remove(key))
 1128  
             {
 1129  
                 // nothing to do
 1130  
             }
 1131  0
             _keys.add(key);
 1132  
 
 1133  0
             int views = getNumberOfViewsInSession(context);
 1134  0
             while (_keys.size() > views)
 1135  
             {
 1136  0
                 key = _keys.remove(0);
 1137  0
                 Object oldView = _serializedViews.remove(key);
 1138  0
                 if (oldView != null && 
 1139  
                     !CACHE_OLD_VIEWS_IN_SESSION_MODE_OFF.equals(getCacheOldViewsInSessionMode(context))) 
 1140  
                 {
 1141  0
                     getOldSerializedViewsMap().put(key, oldView);
 1142  
                 }
 1143  0
             }
 1144  0
         }
 1145  
 
 1146  
         /**
 1147  
          * Reads the amount (default = 20) of views to be stored in session.
 1148  
          * @see #NUMBER_OF_VIEWS_IN_SESSION_PARAM
 1149  
          * @param context FacesContext for the current request, we are processing
 1150  
          * @return Number vf views stored in the session
 1151  
          */
 1152  
         protected int getNumberOfViewsInSession(FacesContext context)
 1153  
         {
 1154  0
             String value = context.getExternalContext().getInitParameter(
 1155  
                     NUMBER_OF_VIEWS_IN_SESSION_PARAM);
 1156  0
             int views = DEFAULT_NUMBER_OF_VIEWS_IN_SESSION;
 1157  0
             if (value != null)
 1158  
             {
 1159  
                 try
 1160  
                 {
 1161  0
                     views = Integer.parseInt(value);
 1162  0
                     if (views <= 0)
 1163  
                     {
 1164  0
                         log.severe("Configured value for " + NUMBER_OF_VIEWS_IN_SESSION_PARAM
 1165  
                                   + " is not valid, must be an value > 0, using default value ("
 1166  
                                   + DEFAULT_NUMBER_OF_VIEWS_IN_SESSION);
 1167  0
                         views = DEFAULT_NUMBER_OF_VIEWS_IN_SESSION;
 1168  
                     }
 1169  
                 }
 1170  0
                 catch (Throwable e)
 1171  
                 {
 1172  0
                     log.log(Level.SEVERE, "Error determining the value for " + NUMBER_OF_VIEWS_IN_SESSION_PARAM
 1173  
                               + ", expected an integer value > 0, using default value ("
 1174  
                               + DEFAULT_NUMBER_OF_VIEWS_IN_SESSION + "): " + e.getMessage(), e);
 1175  0
                 }
 1176  
             }
 1177  0
             return views;
 1178  
         }
 1179  
 
 1180  
         /**
 1181  
          * @return old serialized views map
 1182  
          */
 1183  
         @SuppressWarnings("unchecked")
 1184  
         protected Map<Object, Object> getOldSerializedViewsMap()
 1185  
         {
 1186  0
             FacesContext context = FacesContext.getCurrentInstance();
 1187  0
             if (_oldSerializedViews == null && context != null)
 1188  
             {
 1189  0
                 String cacheMode = getCacheOldViewsInSessionMode(context); 
 1190  0
                 if (CACHE_OLD_VIEWS_IN_SESSION_MODE_WEAK.equals(cacheMode))
 1191  
                 {
 1192  0
                     _oldSerializedViews = new ReferenceMap(AbstractReferenceMap.WEAK, AbstractReferenceMap.WEAK, true);
 1193  
                 }
 1194  0
                 else if (CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT_WEAK.equals(cacheMode))
 1195  
                 {
 1196  0
                     _oldSerializedViews = new ReferenceMap(AbstractReferenceMap.SOFT, AbstractReferenceMap.WEAK, true);
 1197  
                 }
 1198  0
                 else if (CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT.equals(cacheMode))
 1199  
                 {
 1200  0
                     _oldSerializedViews = new ReferenceMap(AbstractReferenceMap.SOFT, AbstractReferenceMap.SOFT, true);
 1201  
                 }
 1202  0
                 else if (CACHE_OLD_VIEWS_IN_SESSION_MODE_HARD_SOFT.equals(cacheMode))
 1203  
                 {
 1204  0
                     _oldSerializedViews = new ReferenceMap(AbstractReferenceMap.HARD, AbstractReferenceMap.SOFT);
 1205  
                 }
 1206  
             }
 1207  
             
 1208  0
             return _oldSerializedViews;
 1209  
         }
 1210  
         
 1211  
         /**
 1212  
          * Reads the value of the <code>org.apache.myfaces.CACHE_OLD_VIEWS_IN_SESSION_MODE</code> context parameter.
 1213  
          * 
 1214  
          * @since 1.2.5
 1215  
          * @param context
 1216  
          * @return constant indicating caching mode
 1217  
          * @see #CACHE_OLD_VIEWS_IN_SESSION_MODE
 1218  
          */
 1219  
         protected String getCacheOldViewsInSessionMode(FacesContext context)
 1220  
         {
 1221  0
             String value = context.getExternalContext().getInitParameter(
 1222  
                     CACHE_OLD_VIEWS_IN_SESSION_MODE);
 1223  0
             if (value == null)
 1224  
             {
 1225  0
                 return CACHE_OLD_VIEWS_IN_SESSION_MODE_OFF;
 1226  
             }
 1227  0
             else if (value.equalsIgnoreCase(CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT))
 1228  
             {
 1229  0
                 return CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT;
 1230  
             }
 1231  0
             else if (value.equalsIgnoreCase(CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT_WEAK))
 1232  
             {
 1233  0
                 return CACHE_OLD_VIEWS_IN_SESSION_MODE_SOFT_WEAK;
 1234  
             }            
 1235  0
             else if (value.equalsIgnoreCase(CACHE_OLD_VIEWS_IN_SESSION_MODE_WEAK))
 1236  
             {
 1237  0
                 return CACHE_OLD_VIEWS_IN_SESSION_MODE_WEAK;
 1238  
             }
 1239  0
             else if (value.equalsIgnoreCase(CACHE_OLD_VIEWS_IN_SESSION_MODE_HARD_SOFT))
 1240  
             {
 1241  0
                 return CACHE_OLD_VIEWS_IN_SESSION_MODE_HARD_SOFT;
 1242  
             }
 1243  
             else
 1244  
             {
 1245  0
                 return CACHE_OLD_VIEWS_IN_SESSION_MODE_OFF;
 1246  
             }
 1247  
         }
 1248  
         
 1249  
         public Object get(Integer sequence, String viewId)
 1250  
         {
 1251  0
             Object key = new SerializedViewKey(viewId, sequence);
 1252  0
             Object value = _serializedViews.get(key);
 1253  0
             if (value == null)
 1254  
             {
 1255  0
                 Map<Object,Object> oldSerializedViewMap = getOldSerializedViewsMap();
 1256  0
                 if (oldSerializedViewMap != null)
 1257  
                 {
 1258  0
                     value = oldSerializedViewMap.get(key);
 1259  
                 }
 1260  
             }
 1261  0
             return value;
 1262  
         }
 1263  
     }
 1264  
 
 1265  
     protected static class SerializedViewKey implements Serializable
 1266  
     {
 1267  
         private static final long serialVersionUID = -1170697124386063642L;
 1268  
 
 1269  
         private final String _viewId;
 1270  
         private final Integer _sequenceId;
 1271  
 
 1272  
         public SerializedViewKey(String viewId, Integer sequence)
 1273  0
         {
 1274  0
             _sequenceId = sequence;
 1275  0
             _viewId = viewId;
 1276  0
         }
 1277  
 
 1278  
         public SerializedViewKey(FacesContext context)
 1279  0
         {
 1280  0
             _sequenceId = RendererUtils.getViewSequence(context);
 1281  0
             _viewId = context.getViewRoot().getViewId();
 1282  0
         }
 1283  
 
 1284  
         @Override
 1285  
         public int hashCode()
 1286  
         {
 1287  0
             final int prime = 31;
 1288  0
             int result = 1;
 1289  0
             result = prime * result + ((_sequenceId == null) ? 0 : _sequenceId.hashCode());
 1290  0
             result = prime * result + ((_viewId == null) ? 0 : _viewId.hashCode());
 1291  0
             return result;
 1292  
         }
 1293  
 
 1294  
         @Override
 1295  
         public boolean equals(Object obj)
 1296  
         {
 1297  0
             if (this == obj)
 1298  
             {
 1299  0
                 return true;
 1300  
             }
 1301  0
             if (obj == null)
 1302  
             {
 1303  0
                 return false;
 1304  
             }
 1305  0
             if (getClass() != obj.getClass())
 1306  
             {
 1307  0
                 return false;
 1308  
             }
 1309  0
             final SerializedViewKey other = (SerializedViewKey) obj;
 1310  0
             if (_sequenceId == null)
 1311  
             {
 1312  0
                 if (other._sequenceId != null)
 1313  
                 {
 1314  0
                     return false;
 1315  
                 }
 1316  
             }
 1317  0
             else if (!_sequenceId.equals(other._sequenceId))
 1318  
             {
 1319  0
                 return false;
 1320  
             }
 1321  0
             if (_viewId == null)
 1322  
             {
 1323  0
                 if (other._viewId != null)
 1324  
                 {
 1325  0
                     return false;
 1326  
                 }
 1327  
             }
 1328  0
             else if (!_viewId.equals(other._viewId))
 1329  
             {
 1330  0
                 return false;
 1331  
             }
 1332  0
             return true;
 1333  
         }
 1334  
 
 1335  
     }
 1336  
 }