Coverage Report - org.apache.myfaces.application.StateManagerImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
StateManagerImpl
0%
0/142
0%
0/80
5.8
 
 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;
 20  
 
 21  
 import java.io.IOException;
 22  
 import java.util.ArrayList;
 23  
 import java.util.HashSet;
 24  
 import java.util.List;
 25  
 import java.util.Set;
 26  
 import java.util.logging.Level;
 27  
 import java.util.logging.Logger;
 28  
 
 29  
 import javax.faces.FactoryFinder;
 30  
 import javax.faces.application.StateManager;
 31  
 import javax.faces.component.NamingContainer;
 32  
 import javax.faces.component.UIComponent;
 33  
 import javax.faces.component.UIComponentBase;
 34  
 import javax.faces.component.UIViewRoot;
 35  
 import javax.faces.context.FacesContext;
 36  
 import javax.faces.render.RenderKit;
 37  
 import javax.faces.render.RenderKitFactory;
 38  
 import javax.faces.render.ResponseStateManager;
 39  
 import javax.faces.view.StateManagementStrategy;
 40  
 import javax.faces.view.ViewDeclarationLanguage;
 41  
 
 42  
 import org.apache.myfaces.application.viewstate.StateCacheUtils;
 43  
 import org.apache.myfaces.context.RequestViewContext;
 44  
 
 45  
 public class StateManagerImpl extends StateManager
 46  
 {
 47  0
     private static final Logger log = Logger.getLogger(StateManagerImpl.class.getName());
 48  
     
 49  0
     private static final String SERIALIZED_VIEW_REQUEST_ATTR = 
 50  
         StateManagerImpl.class.getName() + ".SERIALIZED_VIEW";
 51  
     
 52  0
     private RenderKitFactory _renderKitFactory = null;
 53  
     
 54  
     public StateManagerImpl()
 55  0
     {
 56  0
     }
 57  
 
 58  
     @Override
 59  
     protected Object getComponentStateToSave(FacesContext facesContext)
 60  
     {
 61  0
         if (log.isLoggable(Level.FINEST))
 62  
         {
 63  0
             log.finest("Entering getComponentStateToSave");
 64  
         }
 65  
 
 66  0
         UIViewRoot viewRoot = facesContext.getViewRoot();
 67  0
         if (viewRoot.isTransient())
 68  
         {
 69  0
             return null;
 70  
         }
 71  
 
 72  0
         Object serializedComponentStates = viewRoot.processSaveState(facesContext);
 73  
         //Locale is a state attribute of UIViewRoot and need not be saved explicitly
 74  0
         if (log.isLoggable(Level.FINEST))
 75  
         {
 76  0
             log.finest("Exiting getComponentStateToSave");
 77  
         }
 78  0
         return serializedComponentStates;
 79  
     }
 80  
 
 81  
     /**
 82  
      * Return an object which contains info about the UIComponent type
 83  
      * of each node in the view tree. This allows an identical UIComponent
 84  
      * tree to be recreated later, though all the components will have
 85  
      * just default values for their members.
 86  
      */
 87  
     @Override
 88  
     protected Object getTreeStructureToSave(FacesContext facesContext)
 89  
     {
 90  0
         if (log.isLoggable(Level.FINEST))
 91  
         {
 92  0
             log.finest("Entering getTreeStructureToSave");
 93  
         }
 94  0
         UIViewRoot viewRoot = facesContext.getViewRoot();
 95  0
         if (viewRoot.isTransient())
 96  
         {
 97  0
             return null;
 98  
         }
 99  0
         TreeStructureManager tsm = new TreeStructureManager();
 100  0
         Object retVal = tsm.buildTreeStructureToSave(viewRoot);
 101  0
         if (log.isLoggable(Level.FINEST))
 102  
         {
 103  0
             log.finest("Exiting getTreeStructureToSave");
 104  
         }
 105  0
         return retVal;
 106  
     }
 107  
 
 108  
     @Override
 109  
     public UIViewRoot restoreView(FacesContext facesContext, String viewId, String renderKitId)
 110  
     {
 111  0
         if (log.isLoggable(Level.FINEST))
 112  
         {
 113  0
             log.finest("Entering restoreView - viewId: " + viewId + " ; renderKitId: " + renderKitId);
 114  
         }
 115  
 
 116  0
         UIViewRoot uiViewRoot = null;
 117  
         
 118  0
         ViewDeclarationLanguage vdl = facesContext.getApplication().
 119  
             getViewHandler().getViewDeclarationLanguage(facesContext,viewId);
 120  0
         StateManagementStrategy sms = null; 
 121  0
         if (vdl != null)
 122  
         {
 123  0
             sms = vdl.getStateManagementStrategy(facesContext, viewId);
 124  
         }
 125  
         
 126  0
         if (sms != null)
 127  
         {
 128  0
             if (log.isLoggable(Level.FINEST))
 129  
             {
 130  0
                 log.finest("Redirect to StateManagementStrategy: " + sms.getClass().getName());
 131  
             }
 132  
             
 133  0
             uiViewRoot = sms.restoreView(facesContext, viewId, renderKitId);
 134  
         }
 135  
         else
 136  
         {
 137  0
             RenderKit renderKit = getRenderKitFactory().getRenderKit(facesContext, renderKitId);
 138  0
             ResponseStateManager responseStateManager = renderKit.getResponseStateManager();
 139  
 
 140  0
             Object state = responseStateManager.getState(facesContext, viewId);
 141  
 
 142  0
             if (state != null)
 143  
             {
 144  0
                 Object[] stateArray = (Object[])state;
 145  0
                 TreeStructureManager tsm = new TreeStructureManager();
 146  
                 
 147  0
                 uiViewRoot = tsm.restoreTreeStructure(((Object[])stateArray[0])[0]);
 148  
 
 149  0
                 if (uiViewRoot != null)
 150  
                 {
 151  0
                     facesContext.setViewRoot (uiViewRoot);
 152  0
                     uiViewRoot.processRestoreState(facesContext, stateArray[1]);
 153  
                     
 154  0
                     RequestViewContext.getCurrentInstance(facesContext).refreshRequestViewContext(
 155  
                             facesContext, uiViewRoot);
 156  
                     
 157  
                     // If state is saved fully, there outer f:view tag handler will not be executed,
 158  
                     // so "contracts" attribute will not be set properly. We need to save it and
 159  
                     // restore it from here. With PSS, the view will always be built so it is not
 160  
                     // necessary to save it on the state.
 161  0
                     Object rlc = ((Object[])stateArray[0])[1];
 162  0
                     if (rlc != null)
 163  
                     {
 164  0
                         facesContext.setResourceLibraryContracts((List) UIComponentBase.
 165  
                             restoreAttachedState(facesContext, rlc));
 166  
                     }
 167  
                 }
 168  
             }            
 169  
         }
 170  0
         if (log.isLoggable(Level.FINEST))
 171  
         {
 172  0
             log.finest("Exiting restoreView - " + viewId);
 173  
         }
 174  
 
 175  0
         return uiViewRoot;
 176  
     }
 177  
 
 178  
     /**
 179  
      * Wrap the original method and redirect to VDL StateManagementStrategy when
 180  
      * necessary
 181  
      */
 182  
     @Override
 183  
     public Object saveView(FacesContext facesContext)
 184  
     {
 185  0
         UIViewRoot uiViewRoot = facesContext.getViewRoot();
 186  
         
 187  0
         if (uiViewRoot.isTransient())
 188  
         {
 189  0
             return null;
 190  
         }
 191  
         
 192  0
         Object serializedView = null;
 193  0
         ResponseStateManager responseStateManager = facesContext.getRenderKit().getResponseStateManager();
 194  
         
 195  0
         String viewId = uiViewRoot.getViewId();
 196  0
         ViewDeclarationLanguage vdl = facesContext.getApplication().
 197  
             getViewHandler().getViewDeclarationLanguage(facesContext,viewId);
 198  
         
 199  
         try
 200  
         {
 201  0
             facesContext.getAttributes().put(StateManager.IS_SAVING_STATE, Boolean.TRUE);
 202  0
             if (vdl != null)
 203  
             {
 204  0
                 StateManagementStrategy sms = vdl.getStateManagementStrategy(facesContext, viewId);
 205  
                 
 206  0
                 if (sms != null)
 207  
                 {
 208  0
                     if (log.isLoggable(Level.FINEST))
 209  
                     {
 210  0
                         log.finest("Calling saveView of StateManagementStrategy: " + sms.getClass().getName());
 211  
                     }
 212  
                     
 213  0
                     serializedView = sms.saveView(facesContext);
 214  
                     
 215  
                     // If MyfacesResponseStateManager is used, give the option to do
 216  
                     // additional operations for save the state if is necessary.
 217  0
                     if (StateCacheUtils.isMyFacesResponseStateManager(responseStateManager))
 218  
                     {
 219  0
                         StateCacheUtils.getMyFacesResponseStateManager(responseStateManager).
 220  
                                 saveState(facesContext, serializedView);
 221  
                     }
 222  
                     
 223  0
                     return serializedView; 
 224  
                 }
 225  
             }
 226  
     
 227  
             // In StateManagementStrategy.saveView there is a check for transient at
 228  
             // start, but the same applies for VDL without StateManagementStrategy,
 229  
             // so this should be checked before call parent (note that parent method
 230  
             // does not do this check).
 231  0
             if (uiViewRoot.isTransient())
 232  
             {
 233  0
                 return null;
 234  
             }
 235  
     
 236  0
             if (log.isLoggable(Level.FINEST))
 237  
             {
 238  0
                 log.finest("Entering saveSerializedView");
 239  
             }
 240  
     
 241  0
             checkForDuplicateIds(facesContext, facesContext.getViewRoot(), new HashSet<String>());
 242  
     
 243  0
             if (log.isLoggable(Level.FINEST))
 244  
             {
 245  0
                 log.finest("Processing saveSerializedView - Checked for duplicate Ids");
 246  
             }
 247  
     
 248  
             // SerializedView already created before within this request?
 249  0
             serializedView = facesContext.getAttributes().get(SERIALIZED_VIEW_REQUEST_ATTR);
 250  0
             if (serializedView == null)
 251  
             {
 252  0
                 if (log.isLoggable(Level.FINEST))
 253  
                 {
 254  0
                     log.finest("Processing saveSerializedView - create new serialized view");
 255  
                 }
 256  
     
 257  
                 // first call to saveSerializedView --> create SerializedView
 258  0
                 Object treeStruct = getTreeStructureToSave(facesContext);
 259  0
                 Object compStates = getComponentStateToSave(facesContext);
 260  0
                 Object rlcStates = !facesContext.getResourceLibraryContracts().isEmpty() ? 
 261  
                     UIComponentBase.saveAttachedState(facesContext, 
 262  
                                 new ArrayList<String>(facesContext.getResourceLibraryContracts())) : null;
 263  0
                 serializedView = new Object[] {
 264  
                         new Object[]{treeStruct, rlcStates} ,
 265  
                         compStates};
 266  0
                 facesContext.getAttributes().put(SERIALIZED_VIEW_REQUEST_ATTR,
 267  
                                                     serializedView);
 268  
     
 269  0
                 if (log.isLoggable(Level.FINEST))
 270  
                 {
 271  0
                     log.finest("Processing saveSerializedView - new serialized view created");
 272  
                 }
 273  
             }
 274  
             
 275  
             // If MyfacesResponseStateManager is used, give the option to do
 276  
             // additional operations for save the state if is necessary.
 277  0
             if (StateCacheUtils.isMyFacesResponseStateManager(responseStateManager))
 278  
             {
 279  0
                 StateCacheUtils.getMyFacesResponseStateManager(responseStateManager).
 280  
                         saveState(facesContext, serializedView);
 281  
             }
 282  
     
 283  0
             if (log.isLoggable(Level.FINEST))
 284  
             {
 285  0
                 log.finest("Exiting saveView");
 286  
             }
 287  
         }
 288  
         finally
 289  
         {
 290  0
             facesContext.getAttributes().remove(StateManager.IS_SAVING_STATE);
 291  0
         }
 292  
 
 293  0
         return serializedView;
 294  
     }
 295  
 
 296  
     private static void checkForDuplicateIds(FacesContext context,
 297  
                                              UIComponent component,
 298  
                                              Set<String> ids)
 299  
     {
 300  0
         String id = component.getId();
 301  0
         if (id != null && !ids.add(id))
 302  
         {
 303  0
             throw new IllegalStateException("Client-id : " + id +
 304  
                                             " is duplicated in the faces tree. Component : " + 
 305  
                                             component.getClientId(context)+", path: " +
 306  
                                             getPathToComponent(component));
 307  
         }
 308  
         
 309  0
         if (component instanceof NamingContainer)
 310  
         {
 311  0
             ids = new HashSet<String>();
 312  
         }
 313  
         
 314  0
         int facetCount = component.getFacetCount();
 315  0
         if (facetCount > 0)
 316  
         {
 317  0
             for (UIComponent facet : component.getFacets().values())
 318  
             {
 319  0
                 checkForDuplicateIds (context, facet, ids);
 320  0
             }
 321  
         }
 322  0
         for (int i = 0, childCount = component.getChildCount(); i < childCount; i++)
 323  
         {
 324  0
             UIComponent child = component.getChildren().get(i);
 325  0
             checkForDuplicateIds (context, child, ids);
 326  
         }
 327  0
     }
 328  
 
 329  
     private static String getPathToComponent(UIComponent component)
 330  
     {
 331  0
         StringBuffer buf = new StringBuffer();
 332  
 
 333  0
         if(component == null)
 334  
         {
 335  0
             buf.append("{Component-Path : ");
 336  0
             buf.append("[null]}");
 337  0
             return buf.toString();
 338  
         }
 339  
 
 340  0
         getPathToComponent(component,buf);
 341  
 
 342  0
         buf.insert(0,"{Component-Path : ");
 343  0
         buf.append("}");
 344  
 
 345  0
         return buf.toString();
 346  
     }
 347  
 
 348  
     private static void getPathToComponent(UIComponent component, StringBuffer buf)
 349  
     {
 350  0
         if(component == null)
 351  
         {
 352  0
             return;
 353  
         }
 354  
 
 355  0
         StringBuffer intBuf = new StringBuffer();
 356  
 
 357  0
         intBuf.append("[Class: ");
 358  0
         intBuf.append(component.getClass().getName());
 359  0
         if(component instanceof UIViewRoot)
 360  
         {
 361  0
             intBuf.append(",ViewId: ");
 362  0
             intBuf.append(((UIViewRoot) component).getViewId());
 363  
         }
 364  
         else
 365  
         {
 366  0
             intBuf.append(",Id: ");
 367  0
             intBuf.append(component.getId());
 368  
         }
 369  0
         intBuf.append("]");
 370  
 
 371  0
         buf.insert(0,intBuf.toString());
 372  
 
 373  0
         getPathToComponent(component.getParent(),buf);
 374  0
     }
 375  
 
 376  
     @Override
 377  
     public void writeState(FacesContext facesContext,
 378  
                            Object state) throws IOException
 379  
     {
 380  0
         if (log.isLoggable(Level.FINEST))
 381  
         {
 382  0
             log.finest("Entering writeState");
 383  
         }
 384  
 
 385  
         //UIViewRoot uiViewRoot = facesContext.getViewRoot();
 386  
         //save state in response (client)
 387  0
         RenderKit renderKit = facesContext.getRenderKit();
 388  0
         ResponseStateManager responseStateManager = renderKit.getResponseStateManager();
 389  
 
 390  0
         responseStateManager.writeState(facesContext, state);
 391  
 
 392  0
         if (log.isLoggable(Level.FINEST))
 393  
         {
 394  0
             log.finest("Exiting writeState");
 395  
         }
 396  
 
 397  0
     }
 398  
 
 399  
     //helpers
 400  
 
 401  
     protected RenderKitFactory getRenderKitFactory()
 402  
     {
 403  0
         if (_renderKitFactory == null)
 404  
         {
 405  0
             _renderKitFactory = (RenderKitFactory)FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
 406  
         }
 407  0
         return _renderKitFactory;
 408  
     }
 409  
 
 410  
 }