Coverage Report - org.apache.myfaces.view.facelets.impl.CacheELFaceletCacheImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
CacheELFaceletCacheImpl
0%
0/77
0%
0/66
3.467
CacheELFaceletCacheImpl$FaceletNode
0%
0/14
N/A
3.467
 
 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.impl;
 20  
 
 21  
 import java.io.IOException;
 22  
 import java.net.URL;
 23  
 import java.net.URLConnection;
 24  
 import java.util.Collections;
 25  
 import java.util.HashSet;
 26  
 import java.util.Map;
 27  
 import java.util.Set;
 28  
 import java.util.concurrent.ConcurrentHashMap;
 29  
 
 30  
 import javax.faces.view.facelets.FaceletContext;
 31  
 import javax.faces.view.facelets.FaceletException;
 32  
 
 33  
 import org.apache.myfaces.shared.resource.ResourceLoaderUtils;
 34  
 import org.apache.myfaces.view.facelets.AbstractFaceletCache;
 35  
 import org.apache.myfaces.view.facelets.AbstractFaceletContext;
 36  
 import org.apache.myfaces.view.facelets.util.ParameterCheck;
 37  
 
 38  
 /**
 39  
  * Extended MyFaces specific FaceletCache implementation that recompile
 40  
  * facelet instance when a template context param is found.
 41  
  * 
 42  
  * @author Leonardo Uribe
 43  
  * @since 2.1.0
 44  
  *
 45  
  */
 46  0
 class CacheELFaceletCacheImpl extends AbstractFaceletCache<DefaultFacelet>
 47  
 {
 48  
 
 49  
     private static final long INFINITE_DELAY = -1;
 50  
     private static final long NO_CACHE_DELAY = 0;
 51  
     
 52  
     /**
 53  
      * FaceletNode is necessary only here, because view metadata and 
 54  
      * composite component metadata are special and does not allow use nested
 55  
      * template tags. View metadata facelet trims everything outside f:metadata
 56  
      * and composite component metadata only takes into account composite:xxx tags,
 57  
      * ignoring ui:xxx tags.
 58  
      */
 59  
     private Map<String, FaceletNode> _facelets;
 60  
     
 61  
     private Map<String, DefaultFacelet> _viewMetadataFacelets;
 62  
     
 63  
     private Map<String, DefaultFacelet> _compositeComponentMetadataFacelets;
 64  
     
 65  
     private long _refreshPeriod;
 66  
     
 67  
     CacheELFaceletCacheImpl(long refreshPeriod)
 68  0
     {
 69  0
         _refreshPeriod = refreshPeriod < 0 ? INFINITE_DELAY : refreshPeriod * 1000;
 70  
 
 71  0
         _facelets = new ConcurrentHashMap<String, FaceletNode>();
 72  
         
 73  0
         _viewMetadataFacelets = new ConcurrentHashMap<String, DefaultFacelet>();
 74  
         
 75  0
         _compositeComponentMetadataFacelets = new ConcurrentHashMap<String, DefaultFacelet>();
 76  0
     }
 77  
 
 78  
     @Override
 79  
     public DefaultFacelet getFacelet(URL url) throws IOException
 80  
     {
 81  0
         ParameterCheck.notNull("url", url);
 82  
         
 83  0
         String key = url.toString();
 84  
         
 85  0
         FaceletNode node = _facelets.get(key);
 86  0
         DefaultFacelet f = node != null ? node.getFacelet() : null;
 87  
         
 88  0
         if (f == null || this.needsToBeRefreshed(f))
 89  
         {
 90  
             //f = this._createFacelet(url);
 91  0
             Set<String> paramsSet = null;
 92  0
             if (node != null)
 93  
             {
 94  0
                 paramsSet = node.getParams();
 95  
             }
 96  0
             f = getMemberFactory().newInstance(url);
 97  0
             if (_refreshPeriod != NO_CACHE_DELAY)
 98  
             {
 99  
                 //Map<String, FaceletNode> newLoc = new HashMap<String, FaceletNode>(_facelets);
 100  
                 //newLoc.put(key, (paramsSet != null && !paramsSet.isEmpty()) ? 
 101  
                 //        new FaceletNode(f, paramsSet) : new FaceletNode(f) );
 102  
                 //_facelets = newLoc;
 103  0
                 _facelets.put(key, (paramsSet != null && !paramsSet.isEmpty()) ? 
 104  
                         new FaceletNode(f, paramsSet) : new FaceletNode(f) );
 105  
             }
 106  
         }
 107  
         
 108  0
         return f;
 109  
     }
 110  
 
 111  
     @Override
 112  
     public DefaultFacelet getFacelet(FaceletContext ctx, URL url) throws IOException
 113  
     {
 114  0
         String key = url.toString();
 115  
         
 116  
         //1. Check that the current parameters on the template are known
 117  
         //   for the template.
 118  
         //2. If all current parameters are known return the template
 119  
         //2. If some current parameter is not known, add the param(s) to the
 120  
         //   template, register the known params in the template context and
 121  
         //   recompile the facelet, to clean up al EL expressions at once.
 122  
 
 123  0
         FaceletNode node = _facelets.get(key);
 124  0
         DefaultFacelet f = (node != null) ? node.getFacelet() : null;
 125  
         
 126  0
         Set<String> paramsSet = Collections.emptySet();
 127  0
         paramsSet = (node != null) ? node.getParams() : paramsSet;
 128  
 
 129  0
         AbstractFaceletContext actx = (AbstractFaceletContext) ctx;
 130  0
         Set<String> knownParameters = actx.getTemplateContext().isKnownParametersEmpty() ?
 131  
             (Set) Collections.emptySet() : actx.getTemplateContext().getKnownParameters();
 132  
         
 133  0
         boolean create = false;
 134  0
         for (String paramKey : knownParameters)
 135  
         {
 136  0
             if (!paramsSet.contains(paramKey))
 137  
             {
 138  0
                 create = true;
 139  0
                 break;
 140  
             }
 141  0
         }
 142  
         
 143  0
         if (f == null || this.needsToBeRefreshed(f) || create)
 144  
         {
 145  
             //f = this._createFacelet(url);
 146  0
             f = getMemberFactory().newInstance(url);
 147  0
             if (_refreshPeriod != NO_CACHE_DELAY)
 148  
             {
 149  
                 //Map<String, FaceletNode> newLoc = new HashMap<String, FaceletNode>(_facelets);
 150  0
                 if (!paramsSet.isEmpty()|| !knownParameters.isEmpty() )
 151  
                 {
 152  0
                     paramsSet = new HashSet(paramsSet);
 153  0
                     paramsSet.addAll(knownParameters);
 154  
                     //newLoc.put(key, new FaceletNode(f, paramsSet));
 155  0
                     _facelets.put(key, new FaceletNode(f, paramsSet));
 156  
                 }
 157  
                 else
 158  
                 {
 159  
                     //newLoc.put(key, new FaceletNode(f));
 160  0
                     _facelets.put(key, new FaceletNode(f));
 161  
                 }
 162  
                 //_facelets = newLoc;
 163  
             }
 164  
         }
 165  
 
 166  0
         if (!paramsSet.isEmpty())
 167  
         {
 168  
             //actx.getTemplateContext().getKnownParameters().addAll(paramsSet);
 169  0
             for (String param : paramsSet)
 170  
             {
 171  0
                 if (!actx.getTemplateContext().containsKnownParameter(param))
 172  
                 {
 173  0
                     actx.getTemplateContext().addKnownParameters(param);
 174  
                 }
 175  0
             }
 176  
         }
 177  
         
 178  0
         return f;
 179  
     }
 180  
     
 181  
     @Override
 182  
     public boolean isFaceletCached(URL url)
 183  
     {
 184  0
         return _facelets.containsKey(url.toString());
 185  
     }
 186  
 
 187  
     @Override
 188  
     public DefaultFacelet getViewMetadataFacelet(URL url) throws IOException
 189  
     {
 190  0
         ParameterCheck.notNull("url", url);
 191  
         
 192  0
         String key = url.toString();
 193  
         
 194  0
         DefaultFacelet f = _viewMetadataFacelets.get(key);
 195  
         
 196  0
         if (f == null || this.needsToBeRefreshed(f))
 197  
         {
 198  
             //f = this._createViewMetadataFacelet(url);
 199  0
             f = getMetadataMemberFactory().newInstance(url);
 200  0
             if (_refreshPeriod != NO_CACHE_DELAY)
 201  
             {
 202  
                 //Map<String, DefaultFacelet> newLoc = new HashMap<String, DefaultFacelet>(_viewMetadataFacelets);
 203  
                 //newLoc.put(key, f);
 204  
                 //_viewMetadataFacelets = newLoc;
 205  0
                 _viewMetadataFacelets.put(key, f);
 206  
             }
 207  
         }
 208  
         
 209  0
         return f;
 210  
     }
 211  
 
 212  
     @Override
 213  
     public boolean isViewMetadataFaceletCached(URL url)
 214  
     {
 215  0
         return _viewMetadataFacelets.containsKey(url.toString());
 216  
     }
 217  
 
 218  
     /**
 219  
      * Template method for determining if the Facelet needs to be refreshed.
 220  
      * 
 221  
      * @param facelet
 222  
      *            Facelet that could have expired
 223  
      * @return true if it needs to be refreshed
 224  
      */
 225  
     protected boolean needsToBeRefreshed(DefaultFacelet facelet)
 226  
     {
 227  
         // if set to 0, constantly reload-- nocache
 228  0
         if (_refreshPeriod == NO_CACHE_DELAY)
 229  
         {
 230  0
             return true;
 231  
         }
 232  
 
 233  
         // if set to -1, never reload
 234  0
         if (_refreshPeriod == INFINITE_DELAY)
 235  
         {
 236  0
             return false;
 237  
         }
 238  
 
 239  0
         long target = facelet.getCreateTime() + _refreshPeriod;
 240  0
         if (System.currentTimeMillis() > target)
 241  
         {
 242  
             // Should check for file modification
 243  
 
 244  
             try
 245  
             {
 246  0
                 URLConnection conn = facelet.getSource().openConnection();
 247  0
                 long lastModified = ResourceLoaderUtils.getResourceLastModified(conn);
 248  
 
 249  0
                 return lastModified == 0 || lastModified > target;
 250  
             }
 251  0
             catch (IOException e)
 252  
             {
 253  0
                 throw new FaceletException("Error Checking Last Modified for " + facelet.getAlias(), e);
 254  
             }
 255  
         }
 256  
 
 257  0
         return false;
 258  
     }
 259  
 
 260  
     @Override
 261  
     public DefaultFacelet getCompositeComponentMetadataFacelet(URL url) throws IOException
 262  
     {
 263  0
         ParameterCheck.notNull("url", url);
 264  
 
 265  0
         String key = url.toString();
 266  
 
 267  0
         DefaultFacelet f = _compositeComponentMetadataFacelets.get(key);
 268  
 
 269  0
         if (f == null || this.needsToBeRefreshed(f))
 270  
         {
 271  0
             f = getCompositeComponentMetadataMemberFactory().newInstance(url);
 272  0
             if (_refreshPeriod != NO_CACHE_DELAY)
 273  
             {
 274  
                 //Map<String, DefaultFacelet> newLoc
 275  
                 //        = new HashMap<String, DefaultFacelet>(_compositeComponentMetadataFacelets);
 276  
                 //newLoc.put(key, f);
 277  
                 //_compositeComponentMetadataFacelets = newLoc;
 278  0
                 _compositeComponentMetadataFacelets.put(key, f);
 279  
             }
 280  
         }
 281  0
         return f;
 282  
     }
 283  
 
 284  
     @Override
 285  
     public boolean isCompositeComponentMetadataFaceletCached(URL url)
 286  
     {
 287  0
         return _compositeComponentMetadataFacelets.containsKey(url.toString());
 288  
     }
 289  
     
 290  
     private static class FaceletNode
 291  
     {
 292  
         private DefaultFacelet facelet;
 293  
         private Set<String> params;
 294  
 
 295  
         public FaceletNode(DefaultFacelet facelet)
 296  0
         {
 297  0
             this.facelet = facelet;
 298  0
             this.params = Collections.emptySet();
 299  0
         }
 300  
         
 301  
         public FaceletNode(DefaultFacelet facelet, Set<String> params)
 302  0
         {
 303  0
             this.facelet = facelet;
 304  0
             this.params = params;
 305  0
         }
 306  
         
 307  
         /**
 308  
          * @return the facelet
 309  
          */
 310  
         public DefaultFacelet getFacelet()
 311  
         {
 312  0
             return facelet;
 313  
         }
 314  
 
 315  
         /**
 316  
          * @param facelet the facelet to set
 317  
          */
 318  
         public void setFacelet(DefaultFacelet facelet)
 319  
         {
 320  0
             this.facelet = facelet;
 321  0
         }
 322  
 
 323  
         /**
 324  
          * @return the params
 325  
          */
 326  
         public Set<String> getParams()
 327  
         {
 328  0
             return params;
 329  
         }
 330  
 
 331  
         /**
 332  
          * @param params the params to set
 333  
          */
 334  
         public void setParams(Set<String> params)
 335  
         {
 336  0
             this.params = params;
 337  0
         }
 338  
         
 339  
     }
 340  
 }