Coverage Report - fr.paris.lutece.portal.service.cache.HeadersPageCachingFilter
 
Classes in this File Line Coverage Branch Coverage Complexity
HeadersPageCachingFilter
0 %
0/60
0 %
0/24
1,938
 
 1  
 /*
 2  
  * Copyright (c) 2002-2017, Mairie de Paris
 3  
  * All rights reserved.
 4  
  *
 5  
  * Redistribution and use in source and binary forms, with or without
 6  
  * modification, are permitted provided that the following conditions
 7  
  * are met:
 8  
  *
 9  
  *  1. Redistributions of source code must retain the above copyright notice
 10  
  *     and the following disclaimer.
 11  
  *
 12  
  *  2. Redistributions in binary form must reproduce the above copyright notice
 13  
  *     and the following disclaimer in the documentation and/or other materials
 14  
  *     provided with the distribution.
 15  
  *
 16  
  *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
 17  
  *     contributors may be used to endorse or promote products derived from
 18  
  *     this software without specific prior written permission.
 19  
  *
 20  
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 21  
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 22  
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 23  
  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
 24  
  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 25  
  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 26  
  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 27  
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 28  
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 29  
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 30  
  * POSSIBILITY OF SUCH DAMAGE.
 31  
  *
 32  
  * License 1.0
 33  
  */
 34  
 package fr.paris.lutece.portal.service.cache;
 35  
 
 36  
 import fr.paris.lutece.portal.service.page.PageEvent;
 37  
 import fr.paris.lutece.portal.service.page.PageEventListener;
 38  
 import fr.paris.lutece.portal.service.page.PageService;
 39  
 
 40  
 import net.sf.ehcache.Cache;
 41  
 import net.sf.ehcache.CacheException;
 42  
 import net.sf.ehcache.CacheManager;
 43  
 import net.sf.ehcache.Ehcache;
 44  
 import net.sf.ehcache.constructs.blocking.BlockingCache;
 45  
 import net.sf.ehcache.constructs.blocking.LockTimeoutException;
 46  
 import net.sf.ehcache.constructs.web.AlreadyCommittedException;
 47  
 import net.sf.ehcache.constructs.web.AlreadyGzippedException;
 48  
 import net.sf.ehcache.constructs.web.filter.FilterNonReentrantException;
 49  
 import net.sf.ehcache.constructs.web.filter.SimpleCachingHeadersPageCachingFilter;
 50  
 
 51  
 import org.apache.log4j.Logger;
 52  
 
 53  
 import java.util.List;
 54  
 
 55  
 import javax.servlet.FilterChain;
 56  
 import javax.servlet.FilterConfig;
 57  
 import javax.servlet.http.HttpServletRequest;
 58  
 import javax.servlet.http.HttpServletResponse;
 59  
 
 60  
 /**
 61  
  * Headers Page Caching Filter based on EHCACHE WEB
 62  
  */
 63  0
 public class HeadersPageCachingFilter extends SimpleCachingHeadersPageCachingFilter implements CacheableService, PageEventListener
 64  
 {
 65  
     private static final String BLOCKING_TIMEOUT_MILLIS = "blockingTimeoutMillis";
 66  
     private static final String INIT_PARAM_CACHE_NAME = "cacheName";
 67  
     private Cache _cache;
 68  0
     private Logger _logger = Logger.getLogger( "lutece.cache" );
 69  
     private boolean _bInit;
 70  0
     private boolean _bEnable = true;
 71  
     private String _strCacheName;
 72  
 
 73  
     /**
 74  
      * {@inheritDoc }
 75  
      */
 76  
     @Override
 77  
     public void doInit( FilterConfig filterConfig ) throws CacheException
 78  
     {
 79  
         // Override to inhibate the startup call made too early
 80  
         // The original treatment is done at the first doFilter call
 81  
         // through the init method below
 82  0
     }
 83  
 
 84  
     /**
 85  
      * Initialization of the filter
 86  
      */
 87  
     private void init( )
 88  
     {
 89  
         // Execute the doInit
 90  0
         synchronized( HeadersPageCachingFilter.class )
 91  
         {
 92  0
             if ( blockingCache == null )
 93  
             {
 94  0
                 _strCacheName = filterConfig.getInitParameter( INIT_PARAM_CACHE_NAME );
 95  0
                 CacheService.getInstance( ).createCache( _strCacheName );
 96  0
                 _cache = CacheManager.getInstance( ).getCache( _strCacheName );
 97  0
                 CacheService.registerCacheableService( this );
 98  0
                 _logger.debug( "Initializing cache : " + _strCacheName );
 99  
 
 100  0
                 setCacheNameIfAnyConfigured( filterConfig );
 101  
 
 102  0
                 final String localCacheName = getCacheName( );
 103  0
                 Ehcache cache = getCacheManager( ).getEhcache( localCacheName );
 104  
 
 105  0
                 if ( cache == null )
 106  
                 {
 107  0
                     throw new CacheException( "cache '" + localCacheName + "' not found in configuration" );
 108  
                 }
 109  
 
 110  0
                 if ( !( cache instanceof BlockingCache ) )
 111  
                 {
 112  
                     // decorate and substitute
 113  0
                     BlockingCache newBlockingCache = new BlockingCache( cache );
 114  0
                     getCacheManager( ).replaceCacheWithDecoratedCache( cache, newBlockingCache );
 115  
                 }
 116  
 
 117  0
                 blockingCache = (BlockingCache) getCacheManager( ).getEhcache( localCacheName );
 118  
 
 119  0
                 Integer blockingTimeoutMillis = parseBlockingCacheTimeoutMillis( filterConfig );
 120  
 
 121  0
                 if ( ( blockingTimeoutMillis != null ) && ( blockingTimeoutMillis > 0 ) )
 122  
                 {
 123  0
                     blockingCache.setTimeoutMillis( blockingTimeoutMillis );
 124  
                 }
 125  
             }
 126  
 
 127  0
             PageService.addPageEventListener( this );
 128  0
         }
 129  
 
 130  0
         _bInit = true;
 131  0
     }
 132  
 
 133  
     /**
 134  
      * Reads the filterConfig for the parameter "blockingTimeoutMillis", and if found, set the blocking timeout. If there is a parsing exception, no timeout is
 135  
      * set.
 136  
      *
 137  
      * @param filterConfig
 138  
      *            The filter config
 139  
      * @return The timeout value
 140  
      */
 141  
     private Integer parseBlockingCacheTimeoutMillis( FilterConfig filterConfig )
 142  
     {
 143  0
         String timeout = filterConfig.getInitParameter( BLOCKING_TIMEOUT_MILLIS );
 144  
 
 145  
         try
 146  
         {
 147  0
             return Integer.parseInt( timeout );
 148  
         }
 149  0
         catch( NumberFormatException e )
 150  
         {
 151  0
             return null;
 152  
         }
 153  
     }
 154  
 
 155  
     /**
 156  
      * {@inheritDoc } This method is overriden to provide the cache name
 157  
      */
 158  
     @Override
 159  
     protected String getCacheName( )
 160  
     {
 161  0
         return _strCacheName;
 162  
     }
 163  
 
 164  
     /**
 165  
      * {@inheritDoc }
 166  
      */
 167  
     @Override
 168  
     protected void doFilter( HttpServletRequest request, HttpServletResponse response, FilterChain chain ) throws AlreadyGzippedException,
 169  
             AlreadyCommittedException, FilterNonReentrantException, LockTimeoutException, Exception
 170  
     {
 171  0
         if ( !_bInit )
 172  
         {
 173  0
             init( );
 174  
         }
 175  
 
 176  0
         if ( _bEnable )
 177  
         {
 178  0
             super.doFilter( request, response, chain );
 179  0
             _logger.debug( "URI served from cache : " + request.getRequestURI( ) );
 180  
         }
 181  
         else
 182  
         {
 183  0
             chain.doFilter( request, response );
 184  
         }
 185  0
     }
 186  
 
 187  
     // Cacheable Service implementation
 188  
     /**
 189  
      * {@inheritDoc }
 190  
      */
 191  
     @Override
 192  
     public boolean isCacheEnable( )
 193  
     {
 194  0
         return _bEnable;
 195  
     }
 196  
 
 197  
     /**
 198  
      * {@inheritDoc }
 199  
      */
 200  
     @Override
 201  
     public int getCacheSize( )
 202  
     {
 203  0
         return _cache.getSize( );
 204  
     }
 205  
 
 206  
     /**
 207  
      * {@inheritDoc }
 208  
      */
 209  
     @Override
 210  
     public void resetCache( )
 211  
     {
 212  0
         _cache.removeAll( );
 213  0
     }
 214  
 
 215  
     /**
 216  
      * {@inheritDoc }
 217  
      */
 218  
     @Override
 219  
     public String getName( )
 220  
     {
 221  0
         return _strCacheName;
 222  
     }
 223  
 
 224  
     /**
 225  
      * {@inheritDoc }
 226  
      */
 227  
     @Override
 228  
     public void enableCache( boolean bEnable )
 229  
     {
 230  0
         _bEnable = bEnable;
 231  
 
 232  0
         if ( ( !_bEnable ) && ( _cache != null ) )
 233  
         {
 234  0
             _cache.removeAll( );
 235  
         }
 236  
 
 237  0
         CacheService.updateCacheStatus( this );
 238  0
     }
 239  
 
 240  
     /**
 241  
      * {@inheritDoc }
 242  
      */
 243  
     @Override
 244  
     public List<String> getKeys( )
 245  
     {
 246  0
         return _cache.getKeys( );
 247  
     }
 248  
 
 249  
     /**
 250  
      * {@inheritDoc }
 251  
      */
 252  
     @Override
 253  
     public int getMaxElements( )
 254  
     {
 255  0
         return _cache.getCacheConfiguration( ).getMaxElementsInMemory( );
 256  
     }
 257  
 
 258  
     /**
 259  
      * {@inheritDoc }
 260  
      */
 261  
     @Override
 262  
     public long getTimeToLive( )
 263  
     {
 264  0
         return _cache.getCacheConfiguration( ).getTimeToLiveSeconds( );
 265  
     }
 266  
 
 267  
     /**
 268  
      * {@inheritDoc }
 269  
      */
 270  
     @Override
 271  
     public long getMemorySize( )
 272  
     {
 273  0
         return _cache.calculateInMemorySize( );
 274  
     }
 275  
 
 276  
     /**
 277  
      * {@inheritDoc }
 278  
      */
 279  
     @Override
 280  
     public String getInfos( )
 281  
     {
 282  0
         return CacheService.getInfos( _cache );
 283  
     }
 284  
 
 285  
     /**
 286  
      * {@inheritDoc }
 287  
      */
 288  
     @Override
 289  
     public void processPageEvent( PageEvent event )
 290  
     {
 291  0
         String strPattern = "page_id=" + event.getPage( ).getId( );
 292  
 
 293  0
         for ( String strKey : (List<String>) blockingCache.getKeys( ) )
 294  
         {
 295  0
             if ( strKey.contains( strPattern ) && ( event.getEventType( ) != PageEvent.PAGE_CREATED ) )
 296  
             {
 297  0
                 blockingCache.remove( strKey );
 298  
             }
 299  0
         }
 300  0
     }
 301  
 }