Coverage Report - org.apache.myfaces.view.impl.DefaultViewScopeHandler
 
Classes in this File Line Coverage Branch Coverage Complexity
DefaultViewScopeHandler
0%
0/63
0%
0/22
2.2
 
 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.impl;
 20  
 
 21  
 import java.math.BigInteger;
 22  
 import java.security.NoSuchAlgorithmException;
 23  
 import java.security.SecureRandom;
 24  
 import java.util.HashSet;
 25  
 import java.util.Map;
 26  
 import java.util.Set;
 27  
 import java.util.concurrent.atomic.AtomicLong;
 28  
 import javax.faces.context.ExternalContext;
 29  
 import javax.faces.context.FacesContext;
 30  
 import org.apache.myfaces.config.ManagedBeanDestroyer;
 31  
 import org.apache.myfaces.config.RuntimeConfig;
 32  
 import org.apache.myfaces.config.annotation.LifecycleProvider;
 33  
 import org.apache.myfaces.config.annotation.LifecycleProviderFactory;
 34  
 import org.apache.myfaces.shared.util.SubKeyMap;
 35  
 import org.apache.myfaces.spi.ViewScopeProvider;
 36  
 
 37  
 /**
 38  
  * Minimal implementation for view scope without CDI but always store
 39  
  * the beans into session.
 40  
  * 
 41  
  * @author Leonardo Uribe
 42  
  */
 43  
 public class DefaultViewScopeHandler extends ViewScopeProvider
 44  
 {
 45  
     private static final String VIEW_SCOPE_PREFIX = "oam.view.SCOPE";
 46  
     
 47  
     private static final String VIEW_SCOPE_PREFIX_KEY = VIEW_SCOPE_PREFIX+".KEY";
 48  
     
 49  
     private static final String VIEW_SCOPE_PREFIX_MAP = VIEW_SCOPE_PREFIX+".MAP";
 50  
     
 51  
     static final char SEPARATOR_CHAR = '.';
 52  
     
 53  
     private final AtomicLong _count;
 54  
     
 55  
     private ManagedBeanDestroyer _mbDestroyer;
 56  
     
 57  
     public DefaultViewScopeHandler()
 58  0
     {
 59  0
         _count = new AtomicLong(_getSeed());
 60  0
     }
 61  
     
 62  
     /**
 63  
      * Returns a cryptographically secure random number to use as the _count seed
 64  
      */
 65  
     private static long _getSeed()
 66  
     {
 67  
         SecureRandom rng;
 68  
         try
 69  
         {
 70  
             // try SHA1 first
 71  0
             rng = SecureRandom.getInstance("SHA1PRNG");
 72  
         }
 73  0
         catch (NoSuchAlgorithmException e)
 74  
         {
 75  
             // SHA1 not present, so try the default (which could potentially not be
 76  
             // cryptographically secure)
 77  0
             rng = new SecureRandom();
 78  0
         }
 79  
 
 80  
         // use 48 bits for strength and fill them in
 81  0
         byte[] randomBytes = new byte[6];
 82  0
         rng.nextBytes(randomBytes);
 83  
 
 84  
         // convert to a long
 85  0
         return new BigInteger(randomBytes).longValue();
 86  
     }
 87  
     
 88  
     /**
 89  
      * Get the next token to be assigned to this request
 90  
      * 
 91  
      * @return
 92  
      */
 93  
     private String _getNextToken()
 94  
     {
 95  
         // atomically increment the value
 96  0
         long nextToken = _count.incrementAndGet();
 97  
 
 98  
         // convert using base 36 because it is a fast efficient subset of base-64
 99  0
         return Long.toString(nextToken, 36);
 100  
     }
 101  
     
 102  
     public void onSessionDestroyed()
 103  
     {
 104  0
         FacesContext facesContext = FacesContext.getCurrentInstance();
 105  0
         if (facesContext.getExternalContext().getSession(false) != null)
 106  
         {
 107  0
             ExternalContext external = facesContext.getExternalContext();
 108  0
             Map<String, Object> sessionMap = external.getSessionMap();
 109  0
             String prefix = VIEW_SCOPE_PREFIX_MAP + SEPARATOR_CHAR;
 110  0
             Set<String> viewScopeIdSet = new HashSet<String>();
 111  0
             for (Map.Entry<String,Object> entry: sessionMap.entrySet())
 112  
             {
 113  0
                 if (entry.getKey() != null && 
 114  
                     entry.getKey().startsWith(prefix))
 115  
                 {
 116  0
                     String viewScopeId = entry.getKey().substring(prefix.length(), 
 117  
                             entry.getKey().indexOf(SEPARATOR_CHAR, prefix.length()));
 118  0
                     viewScopeIdSet.add(viewScopeId);
 119  
                 }
 120  0
             }
 121  0
             if (!viewScopeIdSet.isEmpty())
 122  
             {
 123  0
                 for (String viewScopeId : viewScopeIdSet )
 124  
                 {
 125  0
                     this.destroyViewScopeMap(facesContext, viewScopeId);
 126  0
                 }
 127  
             }
 128  
         }
 129  0
     }
 130  
     
 131  
     public Map<String, Object> createViewScopeMap(FacesContext facesContext, String viewScopeId)
 132  
     {
 133  0
         String fullToken = VIEW_SCOPE_PREFIX_MAP + SEPARATOR_CHAR + viewScopeId + SEPARATOR_CHAR;
 134  0
         Map<String, Object> map = _createSubKeyMap(facesContext, fullToken);
 135  0
         return map;
 136  
     }
 137  
     
 138  
     public Map<String, Object> restoreViewScopeMap(FacesContext facesContext, String viewScopeId)
 139  
     {
 140  0
         String fullToken = VIEW_SCOPE_PREFIX_MAP + SEPARATOR_CHAR + viewScopeId + SEPARATOR_CHAR;
 141  0
         Map<String, Object> map = _createSubKeyMap(facesContext, fullToken);
 142  0
         return map;
 143  
     }
 144  
     
 145  
     private Map<String, Object> _createSubKeyMap(FacesContext context, String prefix)
 146  
     {
 147  0
         ExternalContext external = context.getExternalContext();
 148  0
         Map<String, Object> sessionMap = external.getSessionMap();
 149  
 
 150  0
         return new SubKeyMap<Object>(sessionMap, prefix);
 151  
     }
 152  
     
 153  
     public String generateViewScopeId(FacesContext facesContext)
 154  
     {
 155  
         // To ensure uniqueness in this part we use a counter that 
 156  
         // is stored into session and we add a random number to
 157  
         // make difficult to guess the next number.
 158  0
         ExternalContext externalContext = facesContext.getExternalContext();
 159  0
         Object sessionObj = externalContext.getSession(true);
 160  0
         Integer sequence = null;
 161  
         // synchronized to increase sequence if multiple requests
 162  
         // are handled at the same time for the session
 163  0
         synchronized (sessionObj) 
 164  
         {
 165  0
             Map<String, Object> map = externalContext.getSessionMap();
 166  0
             sequence = (Integer) map.get(VIEW_SCOPE_PREFIX_KEY);
 167  0
             if (sequence == null || sequence.intValue() == Integer.MAX_VALUE)
 168  
             {
 169  0
                 sequence = Integer.valueOf(1);
 170  
             }
 171  
             else
 172  
             {
 173  0
                 sequence = Integer.valueOf(sequence.intValue());
 174  
             }
 175  0
             map.put(VIEW_SCOPE_PREFIX_KEY, sequence);
 176  0
         }
 177  0
         return _getNextToken()+'_'+sequence.toString();
 178  
     }
 179  
 
 180  
     @Override
 181  
     public void destroyViewScopeMap(FacesContext facesContext, String viewScopeId)
 182  
     {
 183  0
         if (facesContext.getExternalContext().getSession(false) != null)
 184  
         {        
 185  0
             String fullToken = VIEW_SCOPE_PREFIX_MAP + SEPARATOR_CHAR + viewScopeId + SEPARATOR_CHAR;
 186  0
             Map<String, Object> map = _createSubKeyMap(facesContext, fullToken);
 187  
             
 188  0
             ManagedBeanDestroyer mbDestroyer = getManagedBeanDestroyer(facesContext.getExternalContext());
 189  0
             for (Map.Entry<String,Object> entry : map.entrySet())
 190  
             {
 191  0
                 mbDestroyer.destroy(entry.getKey(), entry.getValue());
 192  0
             }
 193  
             
 194  0
             map.clear();
 195  
         }
 196  0
     }
 197  
     
 198  
     protected ManagedBeanDestroyer getManagedBeanDestroyer(ExternalContext externalContext)
 199  
     {
 200  0
         if (_mbDestroyer == null)
 201  
         {
 202  0
             RuntimeConfig runtimeConfig = RuntimeConfig.getCurrentInstance(externalContext);
 203  0
             LifecycleProvider lifecycleProvider = LifecycleProviderFactory
 204  
                     .getLifecycleProviderFactory(externalContext).getLifecycleProvider(externalContext);
 205  
 
 206  0
             _mbDestroyer = new ManagedBeanDestroyer(lifecycleProvider, runtimeConfig);
 207  
         }
 208  0
         return _mbDestroyer;
 209  
     }
 210  
 }