Coverage Report - org.apache.myfaces.view.facelets.pool.impl.ViewPoolImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
ViewPoolImpl
0%
0/172
0%
0/88
3.545
 
 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.view.facelets.pool.impl;
 20  
 
 21  
 import java.util.ConcurrentModificationException;
 22  
 import java.util.Iterator;
 23  
 import java.util.Map;
 24  
 import java.util.concurrent.ConcurrentHashMap;
 25  
 import javax.faces.component.UIViewRoot;
 26  
 import javax.faces.context.FacesContext;
 27  
 import org.apache.myfaces.context.RequestViewContext;
 28  
 import org.apache.myfaces.shared.util.WebConfigParamUtils;
 29  
 import org.apache.myfaces.view.facelets.pool.RestoreViewFromPoolResult;
 30  
 import org.apache.myfaces.view.facelets.pool.ViewPool;
 31  
 import org.apache.myfaces.view.facelets.pool.ViewEntry;
 32  
 import org.apache.myfaces.view.facelets.pool.ViewStructureMetadata;
 33  
 import org.apache.myfaces.view.facelets.tag.jsf.FaceletState;
 34  
 
 35  
 /**
 36  
  *
 37  
  * @author Leonardo Uribe
 38  
  */
 39  
 public class ViewPoolImpl extends ViewPool
 40  
 {
 41  
 
 42  
     
 43  
     private static final String SKIP_VIEW_MAP_SAVE_STATE = "oam.viewPool.SKIP_VIEW_MAP_SAVE_STATE";    
 44  
             
 45  
     private Map<MetadataViewKey, ViewPoolEntryHolder > staticStructureViewPool;
 46  
     
 47  
     private Map<MetadataViewKey, Map<DynamicViewKey, ViewPoolEntryHolder>> dynamicStructureViewPool;
 48  
     
 49  
     private Map<MetadataViewKey, ViewPoolEntryHolder > partialStructureViewPool;
 50  
     
 51  
     private final int maxCount;
 52  
     private final int dynamicPartialLimit;
 53  
     
 54  
     private final boolean entryWeak;
 55  
     private final boolean deferredNavigation;
 56  
     
 57  
     // View metadata
 58  
     private Map<MetadataViewKey, ViewStructureMetadata> staticStructureViewMetadataMap;
 59  
     private Map<MetadataViewKey, Map<DynamicViewKey, ViewStructureMetadata>> 
 60  
             dynamicStructureViewMetadataMap;
 61  
     
 62  
     public ViewPoolImpl(FacesContext facesContext, Map<String, String> parameters)
 63  0
     {
 64  0
         staticStructureViewPool = new ConcurrentHashMap<MetadataViewKey, ViewPoolEntryHolder>();
 65  0
         partialStructureViewPool = new ConcurrentHashMap<MetadataViewKey, ViewPoolEntryHolder>();
 66  0
         dynamicStructureViewPool = new ConcurrentHashMap<MetadataViewKey, Map<DynamicViewKey, ViewPoolEntryHolder>>();
 67  0
         maxCount = WebConfigParamUtils.getIntegerInitParameter(facesContext.getExternalContext(),
 68  
                 INIT_PARAM_VIEW_POOL_MAX_POOL_SIZE, 
 69  
                 parameters.containsKey(INIT_PARAM_VIEW_POOL_MAX_POOL_SIZE) ? 
 70  
                     Integer.parseInt(parameters.get(INIT_PARAM_VIEW_POOL_MAX_POOL_SIZE)) :
 71  
                     INIT_PARAM_VIEW_POOL_MAX_POOL_SIZE_DEFAULT);
 72  0
         dynamicPartialLimit = WebConfigParamUtils.getIntegerInitParameter(facesContext.getExternalContext(),
 73  
                 INIT_PARAM_VIEW_POOL_MAX_DYNAMIC_PARTIAL_LIMIT, 
 74  
                 parameters.containsKey(INIT_PARAM_VIEW_POOL_MAX_DYNAMIC_PARTIAL_LIMIT) ?
 75  
                 Integer.parseInt(parameters.get(INIT_PARAM_VIEW_POOL_MAX_DYNAMIC_PARTIAL_LIMIT)) : 
 76  
                 INIT_PARAM_VIEW_POOL_MAX_DYNAMIC_PARTIAL_LIMIT_DEFAULT);
 77  0
         String entryMode = WebConfigParamUtils.getStringInitParameter(facesContext.getExternalContext(),
 78  
                 INIT_PARAM_VIEW_POOL_ENTRY_MODE,
 79  
                 parameters.containsKey(INIT_PARAM_VIEW_POOL_ENTRY_MODE) ?
 80  
                 parameters.get(INIT_PARAM_VIEW_POOL_ENTRY_MODE) :
 81  
                 INIT_PARAM_VIEW_POOL_ENTRY_MODE_DEFAULT);
 82  0
         entryWeak = ENTRY_MODE_WEAK.equals(entryMode);
 83  0
         String deferredNavigationVal = WebConfigParamUtils.getStringInitParameter(facesContext.getExternalContext(),
 84  
                 INIT_PARAM_VIEW_POOL_DEFERRED_NAVIGATION,
 85  
                 parameters.containsKey(INIT_PARAM_VIEW_POOL_DEFERRED_NAVIGATION) ?
 86  
                 parameters.get(INIT_PARAM_VIEW_POOL_DEFERRED_NAVIGATION) :
 87  
                 "false");
 88  0
         deferredNavigation = Boolean.valueOf(deferredNavigationVal);
 89  
         
 90  0
         staticStructureViewMetadataMap = new ConcurrentHashMap<MetadataViewKey, ViewStructureMetadata>();
 91  0
         dynamicStructureViewMetadataMap = new ConcurrentHashMap<MetadataViewKey, 
 92  
                 Map<DynamicViewKey, ViewStructureMetadata>>();
 93  0
     }
 94  
     
 95  
     protected void pushStaticStructureView(FacesContext context, MetadataViewKey key, ViewEntry entry)
 96  
     {
 97  0
         ViewPoolEntryHolder q = staticStructureViewPool.get(key);
 98  0
         if (q == null)
 99  
         {
 100  0
             q = new ViewPoolEntryHolder(maxCount);
 101  0
             staticStructureViewPool.put(key, q);
 102  
         }
 103  0
         q.add(entry);
 104  0
     }
 105  
     
 106  
     protected ViewEntry popStaticStructureView(FacesContext context, MetadataViewKey key)
 107  
     {
 108  0
         ViewPoolEntryHolder q = staticStructureViewPool.get(key);
 109  0
         if (q == null)
 110  
         {
 111  0
             return null;
 112  
         }
 113  0
         ViewEntry entry = q.poll();
 114  0
         if (entry == null)
 115  
         {
 116  0
             return null;
 117  
         }
 118  
         do
 119  
         {
 120  0
             if (entry.activate())
 121  
             {
 122  0
                 return entry;
 123  
             }
 124  0
             entry = q.poll();
 125  
         }
 126  0
         while (entry != null);
 127  0
         return null;
 128  
     }
 129  
     
 130  
     protected void pushPartialStructureView(FacesContext context, MetadataViewKey key, ViewEntry entry)
 131  
     {
 132  0
         ViewPoolEntryHolder q = partialStructureViewPool.get(key);
 133  0
         if (q == null)
 134  
         {
 135  0
             q = new ViewPoolEntryHolder(maxCount);
 136  0
             partialStructureViewPool.put(key, q);
 137  
         }
 138  0
         q.add(entry);
 139  0
     }
 140  
     
 141  
     protected ViewEntry popPartialStructureView(FacesContext context, MetadataViewKey key)
 142  
     {
 143  0
         ViewPoolEntryHolder q = partialStructureViewPool.get(key);
 144  0
         if (q == null)
 145  
         {
 146  0
             return null;
 147  
         }
 148  0
         ViewEntry entry = q.poll();
 149  0
         if (entry == null)
 150  
         {
 151  0
             return null;
 152  
         }
 153  
         do
 154  
         {
 155  0
             if (entry.activate())
 156  
             {
 157  0
                 return entry;
 158  
             }
 159  0
             entry = q.poll();
 160  0
         }while (entry != null);
 161  0
         return null;
 162  
     }
 163  
 
 164  
     /**
 165  
      * Generates an unique key according to the metadata information stored
 166  
      * in the passed UIViewRoot instance that can affect the way how the view is generated. 
 167  
      * By default, the "view" params are the viewId, the locale, the renderKit and 
 168  
      * the contracts associated to the view.
 169  
      * 
 170  
      * @param facesContext
 171  
      * @param root
 172  
      * @return 
 173  
      */
 174  
     protected MetadataViewKey deriveViewKey(FacesContext facesContext,
 175  
                     UIViewRoot root)
 176  
     {
 177  
         MetadataViewKey viewKey; 
 178  0
         if (!facesContext.getResourceLibraryContracts().isEmpty())
 179  
         {
 180  0
             String[] contracts = new String[facesContext.getResourceLibraryContracts().size()];
 181  0
             contracts = facesContext.getResourceLibraryContracts().toArray(contracts);
 182  0
             viewKey = new MetadataViewKeyImpl(root.getViewId(), root.getRenderKitId(), root.getLocale(), contracts);
 183  0
         }
 184  
         else
 185  
         {
 186  0
             viewKey = new MetadataViewKeyImpl(root.getViewId(), root.getRenderKitId(), root.getLocale());
 187  
         }
 188  0
         return viewKey;
 189  
     }
 190  
 
 191  
     protected ViewEntry generateViewEntry(FacesContext facesContext,
 192  
                     UIViewRoot root)
 193  
     {
 194  0
         return entryWeak ? new WeakViewEntry(root) : new SoftViewEntry(root);
 195  
     }
 196  
 
 197  
     protected DynamicViewKey generateDynamicStructureViewKey(FacesContext facesContext, UIViewRoot root,
 198  
             FaceletState faceletDynamicState)
 199  
     {
 200  0
         return new DynamicViewKey(faceletDynamicState);
 201  
     }
 202  
 
 203  
     protected void pushDynamicStructureView(FacesContext context, UIViewRoot root, DynamicViewKey key, ViewEntry entry)
 204  
     {
 205  0
         MetadataViewKey ordinaryKey = deriveViewKey(context, root);
 206  0
         Map<DynamicViewKey, ViewPoolEntryHolder> map = dynamicStructureViewPool.get(ordinaryKey);
 207  0
         if (map == null)
 208  
         {
 209  0
             map = new ConcurrentHashMap<DynamicViewKey, ViewPoolEntryHolder>();
 210  0
             dynamicStructureViewPool.put(ordinaryKey, map);
 211  
         }
 212  0
         ViewPoolEntryHolder q = map.get(key);
 213  0
         if (q == null)
 214  
         {
 215  0
             q = new ViewPoolEntryHolder(maxCount);
 216  0
             map.put(key, q);
 217  
         }
 218  0
         if (!q.add(entry))
 219  
         {
 220  0
             pushPartialStructureView(context, ordinaryKey, entry);
 221  
         }
 222  0
     }
 223  
 
 224  
     protected ViewEntry popDynamicStructureView(FacesContext context, UIViewRoot root, DynamicViewKey key)
 225  
     {
 226  0
         MetadataViewKey ordinaryKey = deriveViewKey(context, root);
 227  0
         Map<DynamicViewKey, ViewPoolEntryHolder> map = dynamicStructureViewPool.get(ordinaryKey);
 228  0
         if (map == null)
 229  
         {
 230  0
             return null;
 231  
         }
 232  0
         ViewPoolEntryHolder q = map.get(key);
 233  0
         if (q == null)
 234  
         {
 235  0
             return null;
 236  
         }
 237  0
         ViewEntry entry = q.poll();
 238  0
         while (entry != null)
 239  
         {
 240  0
             if (entry.activate())
 241  
             {
 242  0
                 return entry;
 243  
             }
 244  0
             entry = q.poll();
 245  
         }
 246  0
         return null;
 247  
     }
 248  
 
 249  
     @Override
 250  
     public void pushStaticStructureView(FacesContext context, UIViewRoot root)
 251  
     {
 252  0
         MetadataViewKey key = deriveViewKey(context, root);
 253  0
         if (staticStructureViewMetadataMap.containsKey(key))
 254  
         {
 255  0
             ViewEntry value = generateViewEntry(context, root);
 256  0
             pushStaticStructureView(context, key, value);
 257  
         }
 258  0
     }
 259  
 
 260  
     @Override
 261  
     public ViewEntry popStaticOrPartialStructureView(FacesContext context, UIViewRoot root)
 262  
     {
 263  0
         MetadataViewKey key = deriveViewKey(context, root);
 264  0
         ViewEntry entry = popStaticStructureView(context, key);
 265  0
         if (entry != null)
 266  
         {
 267  0
             entry.setResult(RestoreViewFromPoolResult.COMPLETE);
 268  
         }
 269  
         else
 270  
         {
 271  0
             entry = popPartialStructureView(context, key);
 272  0
             if (entry != null)
 273  
             {
 274  0
                 entry.setResult(RestoreViewFromPoolResult.REFRESH_REQUIRED);
 275  
             }
 276  
             else
 277  
             {
 278  0
                 Map<DynamicViewKey, ViewPoolEntryHolder> map = dynamicStructureViewPool.get(key);
 279  0
                 if (map != null)
 280  
                 {
 281  
                     try
 282  
                     {
 283  0
                         ViewPoolEntryHolder maxEntry = null;
 284  0
                         long max = -1;
 285  0
                         for (Iterator<ViewPoolEntryHolder> it = map.values().iterator(); it.hasNext();)
 286  
                         {
 287  0
                             ViewPoolEntryHolder e = it.next();
 288  0
                             long count = e.getCount();
 289  0
                             if (count > max && count > dynamicPartialLimit)
 290  
                             {
 291  0
                                 maxEntry = e;
 292  0
                                 max = count;
 293  
                             }
 294  0
                         }
 295  0
                         if (maxEntry != null)
 296  
                         {
 297  0
                             entry = maxEntry.poll();
 298  0
                             if (entry != null)
 299  
                             {
 300  
                                 do
 301  
                                 {
 302  0
                                     if (entry.activate())
 303  
                                     {
 304  0
                                         break;
 305  
                                     }
 306  0
                                     entry = maxEntry.poll();
 307  
                                 }
 308  0
                                 while (entry != null);
 309  0
                                 if (entry != null)
 310  
                                 {
 311  0
                                     entry.setResult(RestoreViewFromPoolResult.REFRESH_REQUIRED);
 312  
                                 }
 313  
                             }
 314  
                         }
 315  
                     }
 316  0
                     catch(ConcurrentModificationException ex)
 317  
                     {
 318  
                         //do nothing
 319  0
                     }
 320  
                 }
 321  
             }
 322  
         }
 323  0
         return entry;
 324  
     }
 325  
 
 326  
     @Override
 327  
     public void pushDynamicStructureView(FacesContext context, UIViewRoot root, 
 328  
             FaceletState faceletDynamicState)
 329  
     {
 330  0
         DynamicViewKey key = (DynamicViewKey) generateDynamicStructureViewKey(context, root, faceletDynamicState);
 331  0
         MetadataViewKey ordinaryKey = deriveViewKey(context, root);
 332  0
         Map<DynamicViewKey, ViewStructureMetadata> map = dynamicStructureViewMetadataMap.get(ordinaryKey);
 333  0
         if (map != null)
 334  
         {
 335  0
             ViewEntry value = generateViewEntry(context, root);
 336  0
             pushDynamicStructureView(context, root, key, value);
 337  
         }        
 338  0
     }
 339  
 
 340  
     @Override
 341  
     public ViewEntry popDynamicStructureView(FacesContext context, UIViewRoot root, 
 342  
             FaceletState faceletDynamicState)
 343  
     {
 344  0
         DynamicViewKey key = generateDynamicStructureViewKey(context, root, faceletDynamicState);
 345  0
         ViewEntry entry = popDynamicStructureView(context, root, key);
 346  0
         if (entry != null)
 347  
         {
 348  0
             entry.setResult(RestoreViewFromPoolResult.COMPLETE);
 349  
         }
 350  0
         return entry;
 351  
     }
 352  
 
 353  
     @Override
 354  
     public void pushPartialStructureView(FacesContext context, UIViewRoot root)
 355  
     {
 356  0
         MetadataViewKey key = deriveViewKey(context, root);
 357  0
         ViewEntry value = generateViewEntry(context, root);
 358  0
         pushPartialStructureView(context, key, value);
 359  0
     }
 360  
 
 361  
     @Override
 362  
     public boolean isWorthToRecycleThisView(FacesContext context, UIViewRoot root)
 363  
     {
 364  0
         MetadataViewKey key = deriveViewKey(context, root);
 365  0
         ViewPoolEntryHolder q = partialStructureViewPool.get(key);
 366  0
         if (q != null && q.isFull())
 367  
         {
 368  0
             return false;
 369  
         }
 370  0
         return true;
 371  
     }
 372  
 
 373  
     @Override
 374  
     public void storeStaticViewStructureMetadata(FacesContext context, UIViewRoot root,
 375  
                 FaceletState faceletState)
 376  
     {
 377  0
         MetadataViewKey key = deriveViewKey(context, root);
 378  0
         if (!staticStructureViewMetadataMap.containsKey(key))
 379  
         {
 380  0
             RequestViewContext rvc = RequestViewContext.getCurrentInstance(context);
 381  0
             Object state = saveViewRootState(context, root);
 382  0
             ViewStructureMetadata metadata = new ViewStructureMetadataImpl(state, 
 383  
                     rvc.getRequestViewMetadata().cloneInstance());
 384  0
             staticStructureViewMetadataMap.put(key, metadata);
 385  
         }
 386  0
     }
 387  
 
 388  
     @Override
 389  
     public ViewStructureMetadata retrieveStaticViewStructureMetadata(FacesContext context, UIViewRoot root)
 390  
     {
 391  0
         MetadataViewKey key = deriveViewKey(context, root);
 392  0
         return staticStructureViewMetadataMap.get(key);
 393  
     }
 394  
 
 395  
     private Object saveViewRootState(FacesContext context, UIViewRoot root)
 396  
     {
 397  
         Object state;
 398  0
         if (root.getViewMap(false) != null)
 399  
         {
 400  
             try
 401  
             {
 402  0
                 context.getAttributes().put(SKIP_VIEW_MAP_SAVE_STATE, Boolean.TRUE);
 403  0
                 state = root.saveState(context);
 404  
             }
 405  
             finally
 406  
             {
 407  0
                 context.getAttributes().remove(SKIP_VIEW_MAP_SAVE_STATE);
 408  0
             }
 409  
         }
 410  
         else
 411  
         {
 412  0
             state = root.saveState(context);
 413  
         }
 414  0
         return state;
 415  
     }
 416  
     
 417  
     @Override
 418  
     public void storeDynamicViewStructureMetadata(FacesContext context, UIViewRoot root,
 419  
             FaceletState faceletDynamicState)
 420  
     {
 421  0
         DynamicViewKey key = (DynamicViewKey) generateDynamicStructureViewKey(context, root, faceletDynamicState);
 422  0
         MetadataViewKey ordinaryKey = deriveViewKey(context, root);
 423  0
         if (!dynamicStructureViewMetadataMap.containsKey(ordinaryKey))
 424  
         {
 425  
             
 426  0
             Map<DynamicViewKey, ViewStructureMetadata> map = dynamicStructureViewMetadataMap.get(ordinaryKey);
 427  0
             if (map == null)
 428  
             {
 429  0
                 map = new ConcurrentHashMap<DynamicViewKey, ViewStructureMetadata>();
 430  0
                 dynamicStructureViewMetadataMap.put(ordinaryKey, map);
 431  
             }
 432  0
             RequestViewContext rvc = RequestViewContext.getCurrentInstance(context);
 433  
             
 434  0
             Object state = saveViewRootState(context, root);
 435  
 
 436  0
             ViewStructureMetadata metadata = new ViewStructureMetadataImpl(state, 
 437  
                     rvc.getRequestViewMetadata().cloneInstance());
 438  0
             map.put(key, metadata);
 439  
         }
 440  0
     }
 441  
 
 442  
     @Override
 443  
     public ViewStructureMetadata retrieveDynamicViewStructureMetadata(FacesContext context, UIViewRoot root,
 444  
             FaceletState  faceletDynamicState)
 445  
     {
 446  0
         DynamicViewKey key = (DynamicViewKey) generateDynamicStructureViewKey(context, root, faceletDynamicState);
 447  0
         MetadataViewKey ordinaryKey = deriveViewKey(context, root);
 448  0
         Map<DynamicViewKey, ViewStructureMetadata> map = dynamicStructureViewMetadataMap.get(ordinaryKey);
 449  0
         if (map != null)
 450  
         {
 451  0
             return map.get(key);
 452  
         }
 453  0
         return null;
 454  
     }
 455  
 
 456  
     /**
 457  
      * @return the deferredNavigation
 458  
      */
 459  
     @Override
 460  
     public boolean isDeferredNavigationEnabled()
 461  
     {
 462  0
         return deferredNavigation;
 463  
     }
 464  
     
 465  
 }